# How to Clean Up All Stopped Containers in Apple Container

> Easily clean up all stopped containers with the `container prune` command. Free up disk space by removing unused containers quickly and efficiently.

- Repository: [Apple/container](https://github.com/apple/container)
- Tags: how-to-guide
- Published: 2026-06-28

---

**The `container prune` command removes every stopped container by filtering for status `.stopped`, calculating disk usage, and deleting each container through the XPC client.**

The Apple Container framework provides a dedicated CLI subcommand and Swift API to clean up all stopped containers. Whether you are scripting maintenance tasks or building a management interface, understanding the underlying implementation in [`ContainerPrune.swift`](https://github.com/apple/container/blob/main/ContainerPrune.swift) helps you reclaim disk space safely and efficiently.

## How the Prune Operation Works

The cleanup logic orchestrates three distinct phases to ensure accurate accounting and safe removal.

### Filter Stopped Containers

The process begins in [`ContainerPrune.swift`](https://github.com/apple/container/blob/main/ContainerPrune.swift) by constructing a `ContainerListFilters` value with `status: .stopped`. The implementation calls `withoutMachines()` to exclude machine containers from the deletion scope, ensuring only user-created stopped containers are targeted. This filter model is defined in [`Sources/ContainerResource/Container/ContainerListFilters.swift`](https://github.com/apple/container/blob/main/Sources/ContainerResource/Container/ContainerListFilters.swift).

### Calculate Reclaimed Space

For each container returned by the filtered list, the command gathers usage data. It invokes `ContainerClient.diskUsage(id:)` to compute the total bytes that will be freed. This step occurs in the client implementation at [`Sources/Services/ContainerAPIService/Client/ContainerClient.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/ContainerClient.swift), which communicates with the container daemon over XPC.

### Execute Deletion

Finally, the prune loop calls `ContainerClient.delete(id:)` for every stopped container. The accumulated disk usage totals are logged to provide immediate feedback on reclaimed storage. All XPC RPCs are handled asynchronously through the `ContainerClient` interface.

## Key Source Files and Architecture

Understanding the file structure clarifies how the components interact:

- **[`Sources/ContainerCommands/Container/ContainerPrune.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Container/ContainerPrune.swift)** – Declares the `container prune` CLI command and implements the pruning flow that wires the filters, client, and deletion loop.
- **[`Sources/Services/ContainerAPIService/Client/ContainerClient.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/ContainerClient.swift)** – The XPC client exposing `list`, `diskUsage`, and `delete` methods that send RPCs to the container daemon.
- **[`Sources/ContainerResource/Container/ContainerListFilters.swift`](https://github.com/apple/container/blob/main/Sources/ContainerResource/Container/ContainerListFilters.swift)** – Model for constructing list filters, including the "stopped" status selector and the `withoutMachines()` helper.

## Practical Code Examples

### Using the CLI

The simplest way to clean up all stopped containers is via the command line:

```sh
container prune

```

This command automatically filters for stopped containers, calculates reclaimed space, and prints the IDs of deleted containers.

### Swift Implementation

To implement the same logic programmatically:

```swift
import ContainerAPIClient
import ContainerResource

let client = ContainerClient()
let stoppedFilters = ContainerListFilters(status: .stopped).withoutMachines()
let stopped = try await client.list(filters: stoppedFilters)

var reclaimed: UInt64 = 0
for c in stopped {
    let size = try await client.diskUsage(id: c.id)
    reclaimed += size
    try await client.delete(id: c.id)
}
print("Removed \(stopped.count) stopped containers, reclaimed \(reclaimed) bytes")

```

### Constructing Filters

When building custom management tools, you can inspect the filter construction:

```swift
let filters = ContainerListFilters(status: .stopped).withoutMachines()
// The filter encodes as JSON for transmission to the daemon
print(filters)

```

## Summary

- The **`container prune`** command targets only containers with status `.stopped` while excluding machine containers via `withoutMachines()`.
- The operation relies on **`ContainerClient`** XPC methods `list`, `diskUsage`, and `delete` to communicate with the container daemon.
- All logic is implemented in **[`ContainerPrune.swift`](https://github.com/apple/container/blob/main/ContainerPrune.swift)**, with supporting filter models in **[`ContainerListFilters.swift`](https://github.com/apple/container/blob/main/ContainerListFilters.swift)**.
- Both CLI and Swift APIs provide accurate byte-level reporting of reclaimed disk space.

## Frequently Asked Questions

### What is the difference between `container prune` and manual deletion?

**Manual deletion** requires you to specify individual container IDs and does not automatically calculate reclaimed space. The **`container prune`** command aggregates all stopped containers, computes total disk usage via `diskUsage(id:)`, and removes them in a single operation with detailed logging.

### Why does the prune command exclude machine containers?

The `withoutMachines()` filter removes infrastructure containers that support the Apple Container runtime itself. According to the source in [`ContainerListFilters.swift`](https://github.com/apple/container/blob/main/ContainerListFilters.swift), machine containers are system-level resources that should persist regardless of user cleanup operations to maintain daemon functionality.

### How does the XPC client communicate with the container daemon?

The **`ContainerClient`** defined in [`ContainerClient.swift`](https://github.com/apple/container/blob/main/ContainerClient.swift) establishes an XPC connection to the container daemon. When you call `list`, `diskUsage`, or `delete`, the client serializes requests and sends them as RPCs, awaiting asynchronous responses before updating the local process with container state or confirmation of deletion.

### Is it safe to run `container prune` on a production system?

**Yes**, provided you verify that no stopped containers contain data you wish to preserve. The command only affects containers with status `.stopped` and leaves running containers untouched. However, the deletion via `delete(id:)` is irreversible, so ensure critical stopped containers are backed up or committed to images before pruning.