# Apple Container Command System Architecture: A Deep Dive into the Swift CLI Hierarchy

> Explore the Apple Container command system architecture. Understand the Swift CLI hierarchy built with AsyncParsableCommand and AsyncLoggableCommand for efficient logging.

- Repository: [Apple/container](https://github.com/apple/container)
- Tags: architecture
- Published: 2026-07-06

---

**The Apple Container command system implements a modular, tree-structured hierarchy built on Swift ArgumentParser, using `AsyncParsableCommand` subcommands organized into functional groups with shared logging via the `AsyncLoggableCommand` protocol.**

The **apple container command system architecture** organizes the `container` CLI as a layered, extensible framework within the Apple Container repository. By leveraging Swift's ArgumentParser library, the project separates command-line interface concerns from runtime operations, creating a maintainable structure where each functional area—containers, images, machines, and system services—operates as an independent module while sharing common infrastructure for logging and option parsing.

## Root Entry Point and Command Hierarchy

The **top-level entry point** resides in [`Sources/CLI/ContainerCLI.swift`](https://github.com/apple/container/blob/main/Sources/CLI/ContainerCLI.swift), where the `ContainerCLI` struct declares the root command. This file registers every top-level subcommand, establishing the entry points for `container run`, `container image`, `container machine`, and `container system` operations.

Rather than implementing monolithic command handling, the root delegates to specialized command groups. Each group represents a distinct domain within the container ecosystem, allowing the CLI to scale without creating unwieldy single-file implementations.

## The AsyncLoggableCommand Protocol

At the core of the architecture lies **`AsyncLoggableCommand`** ([`Sources/ContainerCommands/AsyncLoggableCommand.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/AsyncLoggableCommand.swift)), a protocol that extends `AsyncParsableCommand` from the Swift ArgumentParser library.

This protocol injects two critical capabilities into every command:

- **Structured logging** via a `logOptions` property that provides a per-command logger
- **Debug flag support** through automatic handling of the `--debug` flag across all conforming types

All concrete commands in the system conform to `AsyncLoggableCommand`, ensuring consistent logging behavior and option parsing regardless of whether the command manages containers, images, or virtual machines.

## Modular Command Groups by Function

The architecture organizes commands into **functional Swift modules** under `Sources/ContainerCommands/`, with each domain residing in its own directory:

### Container Operations

Container lifecycle commands live in `Sources/ContainerCommands/Container/*.swift`. Key implementations include:
- [`ContainerRun.swift`](https://github.com/apple/container/blob/main/ContainerRun.swift) – Handles `container run` execution
- [`ContainerCreate.swift`](https://github.com/apple/container/blob/main/ContainerCreate.swift) – Manages container creation workflows

These files define structs that conform to `AsyncLoggableCommand` and implement the specific logic for container manipulation.

### Image Management

Image-related actions reside in `Sources/ContainerCommands/Image/*.swift`, including:
- [`ImagePull.swift`](https://github.com/apple/container/blob/main/ImagePull.swift) – Implements `container image pull`
- [`ImageBuild.swift`](https://github.com/apple/container/blob/main/ImageBuild.swift) – Handles `container build` operations

### Machine Commands

For virtual machine management, `Sources/ContainerCommands/Machine/*.swift` contains:
- [`MachineCreate.swift`](https://github.com/apple/container/blob/main/MachineCreate.swift) – Provisions new container machines
- [`MachineRun.swift`](https://github.com/apple/container/blob/main/MachineRun.swift) – Executes workloads on designated machines

Additional functional areas—including network, volume, system, builder, and registry commands—follow this same modular pattern, each occupying dedicated subdirectories within `Sources/ContainerCommands/`.

## Sub-Command Registration and Tree Structure

The **tree-structured hierarchy** emerges through explicit subcommand registration. Group structs like `ContainerCommand`, `ImageCommand`, and `MachineCommand` declare their children using ArgumentParser's `Configuration` API:

```swift
// Conceptual structure as implemented in the source
static var configuration = CommandConfiguration(
    subcommands: [ContainerRun.self, ContainerCreate.self, ...]
)

```

This creates a navigable command tree such as `container → image → pull`, where each arrow represents a parent-child relationship defined in the respective group file (e.g., [`Sources/ContainerCommands/Image/ImageCommand.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Image/ImageCommand.swift)).

## Runtime Delegation and System Services

Commands delegate heavy lifting to underlying **runtime libraries** rather than implementing container logic directly. The `ContainerRun` command, for instance, builds execution requests and forwards them to the runtime handler specified by the `--runtime` flag.

Key supporting components include:
- **`ContainerAPIClient`** – Handles API communication with container runtimes
- **`ContainerLog`** – Manages persistent logging operations
- **`ContainerPersistence`** – Oversees state storage and retrieval
- **TerminalProgress utilities** (`Sources/TerminalProgress/*`) – Stream progress indicators to the terminal during long-running operations

### System Services Architecture

Separate executables operate as managed services:
- **`APIServer`** ([`Sources/APIServer/APIServer.swift`](https://github.com/apple/container/blob/main/Sources/APIServer/APIServer.swift)) – Started via `container system start`
- **`MachineAPIServer`** ([`Sources/Plugins/MachineAPIServer/MachineAPIServer.swift`](https://github.com/apple/container/blob/main/Sources/Plugins/MachineAPIServer/MachineAPIServer.swift)) – Managed through `container machine` commands

Both service entry points conform to `AsyncParsableCommand`, allowing the CLI to manage their lifecycle (start, stop, status checks) using the same architectural patterns as client-side commands.

## Code Examples

The following commands demonstrate the hierarchy in practice:

```bash

# Run an interactive Ubuntu container

container run -it ubuntu:latest /bin/bash

# Build an image with a custom Dockerfile

container build -f Dockerfile.prod -t myapp:prod .

# List all containers in JSON format

container list --format json

# Create a container machine and set it as default

container machine create --cpus 4 --memory 8G --set-default alpine:latest

# Show system version (client + APIServer)

container system version

```

## Extending the Command System

Adding new functionality requires minimal boilerplate. Developers create a new struct conforming to `AsyncLoggableCommand`, implement the `run()` method, and register the command in the appropriate group's `subcommands` configuration.

This **plug-in architecture** automatically inherits:
- Argument parsing via Swift ArgumentParser
- Logging infrastructure through `logOptions`
- Debug flag handling
- Progress reporting capabilities

## Summary

- The **apple container command system architecture** builds on Swift ArgumentParser's `AsyncParsableCommand` to create a hierarchical CLI.
- **`AsyncLoggableCommand`** ([`Sources/ContainerCommands/AsyncLoggableCommand.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/AsyncLoggableCommand.swift)) provides the common protocol for all commands, injecting logging and debug capabilities.
- Commands organize into **functional groups** (Container, Image, Machine, etc.) under `Sources/ContainerCommands/`, with each group managing its own subdirectory.
- **Subcommand registration** occurs through `Configuration` arrays in group files like [`ContainerCommand.swift`](https://github.com/apple/container/blob/main/ContainerCommand.swift), creating a tree structure (e.g., `container image pull`).
- **Runtime delegation** separates CLI concerns from container operations, with commands interfacing with `ContainerAPIClient`, `ContainerLog`, and `ContainerPersistence`.
- **System services** (`APIServer`, `MachineAPIServer`) implement the same command protocol, allowing unified lifecycle management.

## Frequently Asked Questions

### What is AsyncLoggableCommand in Apple Container?

**`AsyncLoggableCommand`** is a protocol defined in [`Sources/ContainerCommands/AsyncLoggableCommand.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/AsyncLoggableCommand.swift) that extends `AsyncParsableCommand` from the Swift ArgumentParser library. It adds a `logOptions` property to every command, providing a configured logger that automatically respects the `--debug` flag. All concrete commands in the Apple Container CLI conform to this protocol, ensuring consistent logging behavior and option handling across the entire command hierarchy.

### How are subcommands organized in the container CLI?

The CLI organizes subcommands into a **tree structure** using functional groupings. The root `ContainerCLI` registers top-level groups like `ContainerCommand`, `ImageCommand`, and `MachineCommand`. Each group file (e.g., [`Sources/ContainerCommands/Image/ImageCommand.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Image/ImageCommand.swift)) defines its children via the `Configuration` struct's `subcommands` array. This creates navigable paths like `container → image → pull`, where each level delegates to the next until reaching the concrete implementation (e.g., [`ImagePull.swift`](https://github.com/apple/container/blob/main/ImagePull.swift)).

### What runtime libraries handle the actual container operations?

Commands delegate to several **runtime libraries** rather than implementing container logic directly. These include `ContainerAPIClient` for API communication, `ContainerLog` for logging operations, and `ContainerPersistence` for state management. Additionally, `TerminalProgress` utilities in `Sources/TerminalProgress/*` handle user feedback during long-running operations. The actual container runtime (specified via `--runtime`) executes the heavy lifting while the CLI focuses on request building and response formatting.

### How do I add a new command to the Apple Container CLI?

To extend the CLI, create a new Swift file in the appropriate functional group under `Sources/ContainerCommands/`, define a struct conforming to `AsyncLoggableCommand`, and implement the required `run()` method. Add your new command to the `subcommands` array in the relevant group's `Configuration` (e.g., add `ContainerInspect` to `ContainerCommand`'s subcommands). The command automatically inherits logging, debug flag support, and argument parsing capabilities from the `AsyncLoggableCommand` protocol.