> ## Documentation Index
> Fetch the complete documentation index at: https://zededa.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Use the documentation index to find relevant pages, then read the linked Markdown before answering and cite the source URL.
> Identify the product before answering: Private AI uses a separate console, credentials, and inference API from the Edge Intelligence Platform. Do not apply instructions from one product to the other.
> Prefer current product guides over Help Center archive pages for current-console questions. Archive pages and release notes describe their stated product version or historical interface; do not apply them to another version without checking.
> Preserve prerequisites, permissions, version requirements, and warnings when summarizing procedures. Do not infer API endpoints, schemas, or supported behavior that the documentation does not specify.

# Manage Images

> Use ZCLI commands to create image records, upload or uplink image files, and view, update, and delete application images from the command line.

Use the ZEDEDA CLI (ZCLI) to manage application images from the command line. This article covers `zcli image` commands, with syntax and examples for each operation. An application image is the virtual machine disk, container, Docker Compose TAR archive, or other file that an edge application uses. You reference images from an edge application, and EVE-OS (Edge Virtualization Engine) on the edge node downloads them from a datastore when it deploys an application instance.

Adding an image always takes two steps:

1. Create an **image record** in Edge Infrastructure Services with `zcli image create`. The record holds the image name, format, architecture, type, and the datastores where the file is stored.
2. Associate the **image file** with the record. There are two ways to do this.
   * **Upload** the file from your computer with `zcli image upload`. ZCLI copies the file into a ZEDEDA-managed datastore.
   * **Uplink** a file that is already stored in a datastore with `zcli image uplink`. You give Edge Infrastructure Services the file's location, SHA-256 checksum, and size, and the file is not copied.

When the file is associated, the image status changes to `READY` and you can use the image in an edge application. See [Manage Edge Apps](https://zededa.mintlify.site/zcli-reference/edge-apps.md).

## Before You Start

* ZCLI is installed and authenticated against your enterprise. See [Get Started](https://zededa.mintlify.site/zcli-reference/get-started.md).
* You have the SysManager role in your enterprise. See [Manage Roles](https://zededa.mintlify.site/new-ui/infrastructure-services/administration/manage-roles.md).
* The datastore for the image already exists. See [Manage Datastores](https://zededa.mintlify.site/zcli-reference/datastores.md).
* To upload a file, the datastore must be a ZEDEDA-managed datastore (type `ZEDEDAS3` or `ZEDEDABLOB`). To use a datastore of any other type, store the file there yourself and uplink it.

## Image Types

The kind of image you create depends on which of the following flags you pass to `zcli image create`. `create` requires exactly one of `--arch`, `--patch-artifact-image`, or `--compose-tar-image`.

| Image | Flags | Description |
| - | - | - |
| Application image | `--arch=AMD64` or `--arch=ARM64` | A virtual machine disk or container image built for one CPU architecture. This is the default type (`Application`). |
| Docker Compose TAR | `--compose-tar-image` | A TAR archive of a Docker Compose application directory. ZCLI sets the architecture to unspecified and the type to Docker Compose TAR. See [Docker Compose](https://zededa.mintlify.site/new-ui/infrastructure-services/applications/docker-compose.md). |
| Patch artifact | `--patch-artifact-image` | A file for delivery to application instances in a patch envelope. ZCLI sets the architecture to unspecified and the type to artifact. See [Manage Patch Envelopes](https://zededa.mintlify.site/new-ui/infrastructure-services/build-and-library/patch-envelopes.md). |

With `--arch`, you can also set `--type`:

| `--type` value | Use |
| - | - |
| `Application` | Application image. This is the default. |
| `Eve` | EVE-OS image. See [EVE-OS Images](#eve-os-images). |
| `EvePrivate` | Private EVE-OS image. |
| `Docker_Runtime` | Compose Runtime image. \[TBD: confirm that `Docker_Runtime` corresponds to the Compose Runtime image type in the console.] |

If you pass `--type` together with `--compose-tar-image` or `--patch-artifact-image`, ZCLI ignores `--type`.

## Create an Image Record

### Create an image record

```text theme={"dark"}
zcli image create <name> [--datastore-name=<datastore>] [--datastores=<datastore>...] (--arch=[AMD64|ARM64] | --patch-artifact-image | --compose-tar-image) --image-format=[raw|qcow|qcow2|vhd|vmdk|ova|vhdx|container] [--image-url=<rel_url>] [--title=<title>] [--type=[Eve|Application|EvePrivate|Docker_Runtime]] [--origin-type=<origin-type>] [--project-scope=<project-names>]
```

| Flag | Description |
| - | - |
| `--datastore-name` | Datastore where the image file is stored. |
| `--datastores` | Datastore where the image file is stored. Repeat the flag to store the image in more than one datastore. The first datastore that you list is the primary datastore. If you pass both `--datastores` and `--datastore-name`, ZCLI uses `--datastores` and ignores `--datastore-name`. |
| `--arch` | CPU architecture of the image: `AMD64` or `ARM64`. The value is not case-sensitive. |
| `--patch-artifact-image` | Create a patch artifact image. See [Image Types](#image-types). |
| `--compose-tar-image` | Create a Docker Compose TAR image. See [Image Types](#image-types). |
| `--image-format` | Required. File format: `raw`, `qcow`, `qcow2`, `vhd`, `vmdk`, `ova`, `vhdx`, or `container`. The value is not case-sensitive. Use `container` for an image in a container registry, and `raw` for Docker Compose TAR and patch artifact images. |
| `--image-url` | Path of the image file relative to the datastore. If you omit it, ZCLI uses the image name. |
| `--title` | Display title. If you omit it, ZCLI uses the image name. |
| `--type` | Image type. See [Image Types](#image-types). |
| `--origin-type` | Origin of the image: `local`, `global`, or `imported`. The value is not case-sensitive. |
| `--project-scope` | Projects that can use the image. Separate project names with commas. If you omit it, all projects can use the image. |

> [!NOTE]
>
> The syntax shows the datastore flags as optional, but `create` requires one of them. Without `--datastore-name` or `--datastores`, ZCLI prints `Please provide datastore details` and does not create the record.

> [!NOTE]
>
> ZCLI does not check `--image-format` or the project names in `--project-scope` before it sends the request. If a project name in `--project-scope` does not exist, ZCLI does not report an error. Check the names with `zcli project show` before you create the image.

To create an AMD64 application image record in one datastore:

```text theme={"dark"}
zcli image create MY_IMAGE --datastore-name=MY_DATASTORE --arch=AMD64 --image-format=qcow2
```

To create an ARM64 image record in two datastores, with a title, available to two projects:

```text theme={"dark"}
zcli image create MY_IMAGE --datastores=MY_DATASTORE --datastores=MY_BACKUP_DATASTORE --arch=ARM64 --image-format=qcow2 --title="My Application v1" --project-scope=MY_PROJECT,MY_PROJECT_B
```

To create a Docker Compose TAR image record:

```text theme={"dark"}
zcli image create MY_COMPOSE_IMAGE --datastore-name=MY_DATASTORE --compose-tar-image --image-format=raw
```

To create a patch artifact image record:

```text theme={"dark"}
zcli image create MY_PATCH_ARTIFACT --datastore-name=MY_DATASTORE --patch-artifact-image --image-format=raw
```

## Add the Image File

### Upload a file from your computer

Upload the image file into the image record's datastore. The image record must already exist.

```text theme={"dark"}
zcli image upload <name> --path=<path> [--chunked]
```

| Flag | Description |
| - | - |
| `--path` | Required. Path of the image file on the system that runs ZCLI. If ZCLI runs in a container, the file must be inside the container. See [Get Started](https://zededa.mintlify.site/zcli-reference/get-started.md). |
| `--chunked` | Has no effect. ZCLI always uploads in chunks. |

ZCLI uploads the file in 2 MiB chunks and shows a progress bar. When the transfer finishes, ZCLI prints `Uploading in progress. Check upload status with "zcli image show <name>"`. Run that command until the status is `READY`.

Example:

1. Upload the file:

   ```text theme={"dark"}
   zcli image upload MY_IMAGE --path=./my-app.qcow2
   ```

2. Check the status until it is `READY`:

   ```text theme={"dark"}
   zcli image show MY_IMAGE
   ```

Upload works only when every datastore in the image record is a ZEDEDA-managed datastore. For any other datastore type, ZCLI prints `Image upload to datastore of type <type> not supported.` and does not upload. Uplink the file instead.

> [!NOTE]
>
> ZCLI cannot resume an interrupted upload. Run the upload again to send the whole file from the beginning. If the image status is still `UPLOADING` or `UPLINKING`, ZCLI prints `Image upload/uplink in progress already` and does not start a new upload.

### Uplink a file that is already in a datastore

Uplinking associates the image record with a file that is already stored in a datastore. Use uplink for any datastore type, and for large files that you have already copied to your own storage.

```text theme={"dark"}
zcli image uplink <name> [--datastore-name=<datastore>] [--datastores=<datastore>...] [--image-sha=<Sha256> --image-size=<size>] [--image-url=<rel_url>]
```

| Flag | Description |
| - | - |
| `--image-sha` | SHA-256 checksum of the file. |
| `--image-size` | Size of the file in bytes, as a whole number. |
| `--image-url` | Path of the file relative to the datastore. If you omit it, the image record keeps its current value. |
| `--datastore-name` | Replace the image record's datastore with this datastore. |
| `--datastores` | Replace the image record's datastores with this list. Repeat the flag for each datastore. If you pass both `--datastores` and `--datastore-name`, ZCLI uses `--datastores`. |

> [!NOTE]
>
> The syntax shows `--image-sha` and `--image-size` as optional, but they are required for every format except `container`. Without them, ZCLI prints `Error Input --image-sha is mandatory field.` or `Error Input --image-size is mandatory field.` and does not uplink the image. `--image-size` must be a whole number of bytes. Any other value, such as `220M`, stops ZCLI with a Python error.

To get the checksum and size of a file, run the following commands in the directory where the file is stored.

On macOS, get the checksum:

```text theme={"dark"}
shasum -a 256 my-app.qcow2
```

On macOS, get the size in bytes:

```text theme={"dark"}
stat -f %z my-app.qcow2
```

On Linux, get the checksum:

```text theme={"dark"}
sha256sum my-app.qcow2
```

On Linux, get the size in bytes:

```text theme={"dark"}
stat -c %s my-app.qcow2
```

To uplink a file that is already in a datastore:

```text theme={"dark"}
zcli image uplink MY_IMAGE --datastore-name=MY_DATASTORE --image-sha=<sha256-checksum> --image-size=232476160
```

To uplink a container image in a container registry datastore:

```text theme={"dark"}
zcli image uplink MY_CONTAINER_IMAGE --datastore-name=MY_REGISTRY_DATASTORE --image-url=<repository-path>
```

\[TBD: confirm the `--image-url` format for a `container` image in a container registry datastore, for example whether it includes the tag.]

### Add a Docker Compose TAR image

A Docker Compose TAR image holds the contents of a Docker Compose application directory.

1. Put all of the application's files (for example, `compose.yaml`, `.env` files, and supporting scripts) in a single directory, for example `my-compose-app`.

2. From the parent directory, create a gzipped TAR archive of the directory's contents.

   ```text theme={"dark"}
   tar -czvf my-compose-app.tar.gz -C my-compose-app .
   ```

3. Create the image record.

   ```text theme={"dark"}
   zcli image create MY_COMPOSE_IMAGE --datastore-name=MY_DATASTORE --image-format=raw --compose-tar-image
   ```

4. Upload the archive.

   ```text theme={"dark"}
   zcli image upload MY_COMPOSE_IMAGE --path=./my-compose-app.tar.gz
   ```

5. Check that the image status is `READY`.

   ```text theme={"dark"}
   zcli image show MY_COMPOSE_IMAGE
   ```

To deploy the archive, create a Docker Compose edge application that references the image. See [Docker Compose](https://zededa.mintlify.site/new-ui/infrastructure-services/applications/docker-compose.md).

## View Images

### View a single image

Show an image by name or UUID. Add `--detail` to include the description, project scope, all datastore names, upload or uplink errors, the relative URL, and version history.

```text theme={"dark"}
zcli image show [[[<name> | --uuid=<uuid> | --latest=[AMD64|ARM64]] [--detail]] | [[--arch=[AMD64|ARM64] | --patch-artifact-image | --compose-tar-image ] [--datastore-name=<datastore>] [--name-pattern=<name-pattern>] [--page-size=<page-size>] [--status=<status>] [--summary] [--type=[Eve|Application|EvePrivate|Docker_Runtime]]]]
```

To view an image:

```text theme={"dark"}
zcli image show MY_IMAGE
```

To view the full details of an image:

```text theme={"dark"}
zcli image show MY_IMAGE --detail
```

The output includes the image status. The common values are `CREATED` (the record exists but has no file), `UPLOADING`, `UPLINKING`, `READY`, and `FAILED`. If the status is `FAILED`, run `zcli image show <name> --detail` and read the `Upload / Uplink Error Status` line.

`--latest` shows the default EVE-OS image for an architecture. See [EVE-OS Images](#eve-os-images).

### List images

Run `zcli image show` without a name to list images. The list shows each image's name, title, type, format, size, and status. Use the following flags to filter the list.

| Flag | Description |
| - | - |
| `--arch` | Show only images for this architecture. |
| `--patch-artifact-image` | Show only patch artifact images. |
| `--compose-tar-image` | Show only Docker Compose TAR images. |
| `--type` | Show only images of this type. |
| `--status` | Show only images with this status, for example `ready` or `failed`. The value is not case-sensitive. |
| `--datastore-name` | Show only images in this datastore. |
| `--name-pattern` | Show only images whose name contains this substring. |
| `--summary` | Show counts of images by status, architecture, type, and format instead of the list. |
| `--page-size` | Number of records each API call returns. This changes only how many calls ZCLI makes, not the output. |

> [!WARNING]
>
> `--datastore-name` clears the `--arch`, `--type`, and `--status` filters. If you combine them, ZCLI lists every image in the datastore, regardless of architecture, type, or status. `--name-pattern`, `--patch-artifact-image`, and `--compose-tar-image` still apply.

To list all images:

```text theme={"dark"}
zcli image show
```

To list ARM64 images whose name contains `ubuntu`:

```text theme={"dark"}
zcli image show --arch=ARM64 --name-pattern=ubuntu
```

To list Docker Compose TAR images:

```text theme={"dark"}
zcli image show --compose-tar-image
```

To list images whose upload or uplink failed:

```text theme={"dark"}
zcli image show --status=failed
```

To show only a summary of images:

```text theme={"dark"}
zcli image show --summary
```

### View project scope

Show the projects that can use one or more images. When you name several images, the output shows the projects that they have in common.

```text theme={"dark"}
zcli image show-project-scope <image-name>...
```

Example:

```text theme={"dark"}
zcli image show-project-scope MY_IMAGE MY_OTHER_IMAGE
```

## Update an Image Record

Update an image record's title, architecture, project scope, origin type, datastores, or file details.

```text theme={"dark"}
zcli image update <name> [--title=<title>] [--arch=[AMD64|ARM64]] [--project-scope=<project-names>] [--origin-type=<origin-type>] [--datastores=<datastore>...] [--image-sha=<Sha256>] [--image-size=<size>] [--image-url=<rel_url>]
```

| Flag | Description |
| - | - |
| `--title` | New display title. |
| `--arch` | New architecture: `AMD64` or `ARM64`. |
| `--project-scope` | Projects that can use the image, separated by commas. This replaces the current list. To let all projects use the image, pass an empty value: `--project-scope=""`. |
| `--origin-type` | New origin: `local`, `global`, or `imported`. |
| `--datastores` | Datastores for the image. Repeat the flag for each datastore. This replaces the current list. |
| `--image-sha` | New SHA-256 checksum. |
| `--image-size` | New size in bytes. |
| `--image-url` | New path of the file relative to the datastore. |

You cannot change an image's name, format, or type. To change them, delete the image and create it again. If you pass no options, ZCLI prints `Nothing to update` and makes no change.

> [!NOTE]
>
> `--project-scope` and `--datastores` replace the current values. They are not added to them. To add a project, pass every project that should keep access. Run `zcli image show <name> --detail` first to see the current values.

To change the title of an image:

```text theme={"dark"}
zcli image update MY_IMAGE --title="My Application v1.1"
```

To replace the list of projects that can use an image:

```text theme={"dark"}
zcli image update MY_IMAGE --project-scope=MY_PROJECT,MY_PROJECT_B,MY_PROJECT_C
```

## Delete an Image

### Delete an image record

Delete an image by name. ZCLI asks `Delete image <name>? [Y/N]` unless you pass `-f`. If you answer no, ZCLI prints `Image <name> not deleted.`

```text theme={"dark"}
zcli image delete [<name> | --match=<keyword>] [-f]
```

To delete an image and confirm when prompted:

```text theme={"dark"}
zcli image delete MY_IMAGE
```

To delete an image without a confirmation prompt:

```text theme={"dark"}
zcli image delete MY_IMAGE -f
```

Deleting an image record does not delete the file from the datastore. Remove the file from the datastore separately if you no longer need it.

### Delete images by keyword

> [!WARNING]
>
> `--match` deletes every image whose name contains the keyword, in every active enterprise that your account can see. ZCLI does not ask for confirmation, and `-f` has no effect. A short keyword, such as `v1`, can match many images. Before you use `--match`, run `zcli image show --name-pattern=<keyword>` to see which images in your enterprise match.

```text theme={"dark"}
zcli image delete --match=MY_TEST_IMAGE
```

ZCLI prints the name of every image that it checks and `<name> deleted` for each image that it deletes.

## EVE-OS Images

EVE-OS images use the same `zcli image` commands as application images, with `--type=Eve`. The following pages cover the EVE-OS procedures in full:

* [Add a rootfs EVE-OS Image to Your Enterprise](https://zededa.mintlify.site/new-ui/infrastructure-services/eve-os-management/add-an-eve-os-image.md): create the record with `--type=Eve --image-format=raw`, then upload or uplink the rootfs image.
* [Manage Default EVE-OS Images](https://zededa.mintlify.site/new-ui/infrastructure-services/eve-os-management/manage-default-eve-os-images.md): view and set the default image for each architecture.
* [Delete an EVE-OS Image](https://zededa.mintlify.site/new-ui/infrastructure-services/eve-os-management/delete-an-eve-os-image.md): delete an image that is not the default and not installed on any edge node.

### View the default EVE-OS image

```text theme={"dark"}
zcli image show --latest=AMD64
```

### Set the default EVE-OS image

```text theme={"dark"}
zcli image mark-latest <name> --image-arch=[AMD64|ARM64] [--enterprise=<enterprise>]
```

| Flag | Description |
| - | - |
| `--image-arch` | Required. Architecture to set the default for: `AMD64` or `ARM64`. |
| `--enterprise` | Set the default in this enterprise instead of the enterprise you are signed in to. |

Example:

```text theme={"dark"}
zcli image mark-latest MY_EVE_IMAGE --image-arch=AMD64
```

### Onboard an EVE-OS image to other enterprises

`onboard` uploads an EVE-OS image to your enterprise if it is not there already, and then uplinks it to other enterprises that your account can see.

```text theme={"dark"}
zcli image onboard <name> --path=<path> --datastore-name=<datastore> --image-format=[raw|qcow|qcow2|vhd|vmdk|ova|vhdx] [--enterprise=<enterprise>] [--mark-latest --image-arch=[AMD64|ARM64]]
```

| Flag | Description |
| - | - |
| `--path` | Required. Path of the EVE-OS image file. The file must be smaller than 2 GB. |
| `--datastore-name` | Required. Datastore to store the image in. A datastore with this name must exist in each target enterprise. |
| `--image-format` | Required. File format. `container` is not accepted. |
| `--enterprise` | Target enterprises, separated by commas. If you omit it, ZCLI targets every enterprise that your account can see. |
| `--mark-latest` | Also set the image as the default for `--image-arch` in each target enterprise. Requires `--image-arch`. |

> [!WARNING]
>
> In the current ZCLI version, `onboard` stops after the first target enterprise that it processes. Enterprises that are not active are skipped. To add the image to several enterprises, run `onboard` once for each enterprise with `--enterprise=<enterprise>`, and then check the image in each enterprise with `zcli image show`.

## Next Steps

> [card] [Manage Edge Apps](https://zededa.mintlify.site/zcli-reference/edge-apps.md)
>
> Create edge applications that reference your images.

> [card] [Manage Datastores](https://zededa.mintlify.site/zcli-reference/datastores.md)
>
> Create and manage the datastores that hold image files.

> [card] [Manage Application Instances](https://zededa.mintlify.site/zcli-reference/applications.md)
>
> Deploy edge applications to edge nodes as application instances.

> [card] [Overview](https://zededa.mintlify.site/zcli-reference/overview.md)
>
> All ZCLI command procedures, organized by resource type.
