How to View Detailed Container Resource Usage in JSON Format with the Container CLI

Use container stats --format json --no-stream to output detailed CPU, memory, network, and block I/O metrics as a machine-readable JSON array.

The apple/container repository provides a daemon-based container runtime that exposes resource metrics through the stats subcommand. When integrating with monitoring systems or processing container metrics programmatically, viewing detailed container resource usage in JSON format offers a structured alternative to the default human-readable table view.

Prerequisites

Before querying resource usage, ensure you have:

  • The Container CLI installed and configured
  • The Container daemon running via XPC
  • At least one running container to query (or access to the system containers)

Enabling JSON Output Mode

The CLI implements static JSON output through the --format json flag combined with --no-stream. This configuration serializes an array of ContainerStats structs using Swift’s JSONEncoder, providing consistent field names and numeric values suitable for pipeline processing.

Why You Must Use --no-stream

By default, the stats command operates in streaming mode, producing a continuously updating display similar to top. When you request JSON format, you must disable this behavior with --no-stream to receive a single snapshot that terminates after the initial data collection. Without this flag, the encoder would attempt to interleave JSON with screen-control sequences, resulting in malformed output.

Technical Implementation Details

The JSON output flow traverses the client-daemon boundary through XPC, with serialization handled in the command layer.

Command Parsing in ContainerStats.swift

In Sources/ContainerCommands/Container/ContainerStats.swift, the command definition declares the --format option using the ListFormat enum and the --no-stream boolean flag. Lines 34-38 define these options, while lines 45-50 implement the logic that detects when to invoke runStatic():

  • If --format json is specified or --no-stream is set, the command enters static mode
  • Static mode gathers metrics once and exits immediately

XPC Communication with ContainerAPIService

When runStatic() executes, it instantiates a ContainerClient and calls client.stats(id:) for each target container. This method communicates with the daemon’s XPC endpoint defined in Sources/Services/ContainerAPIService/Server/Containers/ContainersService.swift at line 790. The server-side ContainersService.stats method returns a ContainerStats struct populated with raw kernel metrics including CPU time, memory pages, and block device statistics.

JSON Encoding and Rendering

After collecting stats, the command passes the array of ContainerStats objects to Output.render(payload:format:). When format == .json, this helper uses JSONEncoder to serialize the data (pretty-printed if --pretty is supplied) and writes the result to stdout. The implementation in Sources/ContainerCommands/Container/ContainerStats.swift lines 105-107 handles the final encoding step before output.

Available JSON Fields

The JSON array contains objects with the following fields from the ContainerStats struct:

  • id – Container identifier
  • cpuUsageUsec – CPU usage in microseconds
  • memoryUsageBytes – Current memory consumption
  • memoryLimitBytes – Memory limit for the container
  • networkRxBytes – Bytes received over network interfaces
  • networkTxBytes – Bytes transmitted over network interfaces
  • blockReadBytes – Total bytes read from block devices
  • blockWriteBytes – Total bytes written to block devices
  • numProcesses – Current process count

Practical Examples

Fetch resource usage for all running containers as a JSON snapshot:

container stats --format json --no-stream

Query a specific container by name:

container stats --format json --no-stream web

Generate pretty-printed JSON for a specific container ID:

container stats --format json --pretty --no-stream abcd1234

Pipe the output to jq for filtering specific metrics:

container stats --format json --no-stream | jq '.[] | {id, memoryUsageBytes}'

Summary

  • Use container stats --format json --no-stream to view detailed container resource usage in JSON format
  • The --no-stream flag is required to prevent continuous updates and ensure valid JSON output
  • The implementation resides in Sources/ContainerCommands/Container/ContainerStats.swift with XPC communication handled by ContainersService.stats at line 790
  • The JSON output includes CPU, memory, network, block I/O, and process metrics defined in the ContainerStats struct
  • Add --pretty for human-readable indentation during debugging

Frequently Asked Questions

Do I need to specify --no-stream every time I use JSON format?

Yes. According to the source code in ContainerStats.swift, the command enters static mode only when --format json or --no-stream is explicitly provided. Without --no-stream, the command attempts to refresh the display continuously, which breaks JSON formatting by inserting terminal control sequences between data frames.

What is the difference between streaming and static mode?

Streaming mode updates resource metrics in real-time using terminal screen refresh sequences, similar to the top command. Static mode, triggered by runStatic(), queries the daemon once via the ContainersService.stats endpoint, encodes the results immediately, and exits. Static mode is required for JSON output and automation scripts.

Can I get pretty-printed JSON instead of compact output?

Yes. Append the --pretty flag to your command. The Output.render(payload:format:) method checks for this option and configures JSONEncoder with pretty-printing enabled, adding line breaks and indentation to the output while maintaining the same data structure.

Where is the ContainerStats data structure defined?

The ContainerStats struct is defined in the ContainerResource module, specifically in Sources/ContainerResource/ContainerStats.swift. This type represents the wire format exchanged between the daemon and CLI, containing the raw numeric metrics for CPU, memory, network, and block I/O that eventually get serialized into your JSON output.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →