Skip to content

Tutorial 3 · A Codex session

Goal: run the Codex CLI the way you would locally — in a project, in your terminal — but inside a pausable Barista session. Same flow as Claude Code, different tool and key.

Prereq: the one-time setup, plus your OPENAI_API_KEY exported locally.

Step 1 — create the session

barista create codex --image node:20-slim -- sh -c '
  apt-get update && apt-get install -y ca-certificates &&
  npm install -g @openai/codex &&
  mkdir -p /work && cd /work &&
  printf "def add(a,b):\n    return a+b\n" > calc.py &&
  sleep infinity'
# {"name": "codex", "status": "pending"}

(Unlike Claude Code — where Node bundles its own CA roots — the Codex CLI is a Rust binary that uses the system trust store, and node:20-slim ships without ca-certificates; skip it and every API call fails with invalid peer certificate: UnknownIssuer.)

Wait for running + install (~1–2 min), then confirm:

barista exec codex -- codex --version     # codex-cli 0.147.0

Step 2 — log the session's Codex in

Recent Codex CLI versions don't read OPENAI_API_KEY from the environment — you log in once and it persists in the session (and survives pause/resume):

export OPENAI_API_KEY=…
barista exec codex --env OPENAI_API_KEY -- \
  sh -c 'printf "%s" "$OPENAI_API_KEY" | codex login --with-api-key'
# Successfully logged in

--env OPENAI_API_KEY (bare) forwards your local value for just this exec; the key never appears on the command line.

Step 3 — attach straight into Codex

Open Codex in the project:

barista attach codex --workdir /work -- codex

You're in interactive Codex, in /work, on a real PTY. Exit to detach; the session keeps running.

Headless mode

Non-interactive, for scripting/CI:

barista exec codex --workdir /work -- \
  codex exec --skip-git-repo-check --dangerously-bypass-approvals-and-sandbox \
  "write tests for calc.py and run them"

Codex's own bubblewrap sandbox can't create namespaces inside the microVM — and doesn't need to: the session is the sandbox (hardware-isolated KVM), so bypassing the inner one is the intended setup here.

Step 4 — pause and resume

barista pause codex        # {"name":"codex","status":"paused"} — clock stops
barista resume codex       # {"name":"codex","status":"running"}
barista attach codex --workdir /work -- codex

On the KVM node the paused VM holds the filesystem and process memory across the freeze, so you pick up where you left off; codex resume also lists prior sessions to reopen (headless: codex exec resume --last "…").

A live run of the whole flow — version check, login, a fib() task, freeze, thaw, and codex exec resume --last continuing the same conversation:

A live Codex run: login, fib() added, pause/resume, and the resumed conversation

Passing the key cleanly

--env OPENAI_API_KEY forwards it per-attach/exec, keeping it out of the session's stored desired-state. For shared keys, prefer the control plane's secrets store.

Clean up

barista rm codex

For a pinned image with both CLIs baked in, the same ../../demos/claude-code/Dockerfile also installs @openai/codex. Next: drive sessions from an MCP client.