Command reference

Updated Oct 17, 2026

Polythene exposes two Cyclopts commands. Both commands accept the optional --store argument to override the root filesystem directory (defaults to /var/tmp/polythene).

Execution environments

Before running commands, decide how they interact with your host. Polythene provides a single interface but adapts to the available tooling:

  • Codex sandbox – You run as root without container engines. The polythene pull command still uses Podman inside the sandbox because Codex maintains the binary on disk, and polythene exec falls back to bwrap, proot, or a privileged chroot.
  • GitHub runners – You run as an unprivileged user with Podman available. The CLI exports images in the same way but typically selects bwrap for execution, providing equivalent isolation to the Codex workflow.

In both environments the exported root filesystem is disposable, enabling repeatable system-level tests without polluting the host.

`polythene pull`

uv run polythene pull docker.io/library/busybox:latest
# or
python -m polythene pull docker.io/library/busybox:latest

The pull command:

  • ensures the store directory exists,
  • probes the active Podman store with podman image exists IMAGE,
  • pulls the image only when that probe reports it absent,
  • exports the image into a UUID-named root filesystem directory, and
  • prints the generated UUID to stdout for later reuse, as the only line written there.

Podman's progress reporting, image IDs, and container IDs are kept off stdout, so polythene pull can be captured with $(...) without filtering. It works the same way with --timeout as without it. To see what Polythene and Podman are doing, set POLYTHENE_VERBOSE (see Environment variables) or read stderr.

Because the probe reads local storage rather than a registry, an image you built in the same job can be reused without publishing it. The probe and the subsequent container creation resolve the same podman command and inherit the same environment, so both see the same Podman store:

podman build --tag localhost/example:latest .
uv run polythene pull localhost/example:latest --store ./polythene-store

Without the probe, Podman would read the localhost component of that reference as a registry host and try to reach https://localhost/v2/, which fails when no registry is listening there.

An image is only reused when it is visible to the Podman user and storage configuration Polythene inherits. Building it with a different --storage-driver, a different CONTAINERS_STORAGE_CONF, or under another user places it in a separate store, and the probe will report it absent so Polythene falls back to pulling it. The same applies when a probe fails for an unrelated reason such as unreadable local storage: Polythene reports that status instead of silently treating the image as missing.

Podman must be installed and available on PATH. When the POLYTHENE_VERBOSE variable is set, the command also prints progress messages to stderr.

`polythene exec`

uv run polythene exec <uuid> -- uname -a
# or
python -m polythene exec <uuid> -- uname -a

Replace <uuid> with the value returned by a previous polythene pull call. The exec command runs a user supplied program inside the exported root filesystem. It picks the first available execution backend in the following order:

  1. bwrap
  2. proot
  3. A privileged chroot

Each backend receives the prepared filesystem as its root and blocks network access. If none of the backends is available, the command fails with an error message detailing the missing tooling.

When a specific backend is preferable, pass --isolation <backend> (or the equivalent --isolation=<backend> form) to reorder the probing sequence. GitHub runners lack user namespace support for bwrap, and specifying --isolation proot avoids the noisy permission errors emitted by bubblewrap before proot succeeds.

Because the same UUID works across hosts, you can prepare an image on Codex and reuse it on CI:

uv run polythene pull registry.example.invalid/tools:latest
uv run polythene exec <uuid> -- make -C /workspace/tests system

The exec invocation will select the available backend on each host while the commands run unchanged.