Codex in Docker

Codex auth/config/cache lives in ~/.config/codex-docker/codex-home. Current directory is mounted into /workspace.

~/.config/codex-docker/docker-compose.yml:

services:
  codex:
    build:
      context: .
      dockerfile_inline: |
        FROM ghcr.io/openai/codex-universal:latest
        RUN bash -lc 'npm i -g @openai/codex@latest'        
    image: local/codex-universal-cli:latest
    volumes:
      - ./codex-home:/root/.codex
      - ${PROJECT_DIR:-.}:/workspace
    working_dir: /workspace
    stdin_open: true
    tty: true
    command: ["-lc", "codex --yolo"]

Fish ~/.config/fish/functions/codex.fish:

function codex
    set -lx PROJECT_DIR "$PWD"
    set -l compose ~/.config/codex-docker/docker-compose.yml

    if test (count $argv) -eq 0
        docker compose -f $compose run --rm codex -lc "codex --yolo"
    else
        set -l escaped_args (string join ' ' -- (string escape -- $argv))
        docker compose -f $compose run --rm codex -lc "codex --yolo $escaped_args"
    end
end

Fish ~/.config/fish/functions/codex-update.fish:

function codex-update
    docker compose -f ~/.config/codex-docker/docker-compose.yml build --no-cache codex
end

Bash:

cat >> ~/.bashrc <<'EOF'
codex() {
  local escaped_args
  printf -v escaped_args '%q ' "$@"

  PROJECT_DIR="$PWD" docker compose -f "$HOME/.config/codex-docker/docker-compose.yml" \
    run --rm codex -lc "codex --yolo $escaped_args"
}

codex-update() {
  docker compose -f "$HOME/.config/codex-docker/docker-compose.yml" build --no-cache codex
}
EOF

codex-update rebuilds the local image and runs npm i -g @openai/codex@latest again.