No description
  • Shell 91.6%
  • Dockerfile 6.6%
  • Makefile 1.8%
Find a file
Claudio Maradonna ec5ccd3133
refactor: remove sessions due to codex token limit
OpenAI checks for multiple token sessions and restricts usage. Can be risky for ToS so simply with 1 session
2026-05-11 23:29:47 +02:00
.claude init from claude-jail :) 2026-05-11 12:59:23 +02:00
.dir-locals.el init from claude-jail :) 2026-05-11 12:59:23 +02:00
.dockerignore init from claude-jail :) 2026-05-11 12:59:23 +02:00
.env.example refactor: remove sessions due to codex token limit 2026-05-11 23:29:47 +02:00
.gitignore init from claude-jail :) 2026-05-11 12:59:23 +02:00
codex.sh refactor: remove sessions due to codex token limit 2026-05-11 23:29:47 +02:00
COPYRIGHT init from claude-jail :) 2026-05-11 12:59:23 +02:00
Dockerfile chore: add TZ argument for custom Timezone 2026-05-11 23:22:25 +02:00
install.sh chore: add TZ argument for custom Timezone 2026-05-11 23:22:25 +02:00
Makefile chore: add TZ argument for custom Timezone 2026-05-11 23:22:25 +02:00
README.md refactor: remove sessions due to codex token limit 2026-05-11 23:29:47 +02:00

Codex Jail

Run the OpenAI Codex CLI inside a rootless Podman container.

Codex needs broad filesystem access to be useful. Running it in a container gives you the convenience of a fully capable coding agent without exposing your entire home directory, system binaries, or credentials beyond what you explicitly mount.

Why a jail?

Codex CLI ships with its own sandbox and approval system, but those primitives still run on top of your real user account. A misconfigured prompt or a sandbox bypass means the agent can touch anything you can. A container inverts the model: Codex sees an empty Debian system, plus only the paths you mount in. The host filesystem, your credentials, and unrelated projects stay out of reach.

Inside the container we pass --dangerously-bypass-approvals-and-sandbox because the container itself is the sandbox — Codex can only act on the explicitly mounted workspace and its own state directory.

Install

git clone https://git.unitoo.it/claudiomaradonna/codex-jail
cd codex-jail
./install.sh

The installer:

  1. Installs Podman if it is not present (apt/dnf/pacman/brew).
  2. Builds the codex-cli:latest image and dual-tags it with the detected Codex CLI version (e.g. codex-cli:0.45.0).
  3. Drops the codex wrapper into ~/.local/bin/.

Make sure ~/.local/bin is in your PATH:

export PATH="${HOME}/.local/bin:${PATH}"

Installer options

./install.sh --image my-codex:dev    # custom image name (skips version dual-tag)
./install.sh --no-cache              # full rebuild bypassing layer cache

Usage

codex .                              # mount current directory
codex . --model gpt-5-codex          # pass native codex flags
codex --with-ssh-agent . exec "fix"  # SSH agent + non-interactive exec mode
codex --image my-image .             # use a custom image
codex . --mount /data:/data:ro       # mount /data as read-only
codex --help                         # full option list

Anything the wrapper does not recognise is forwarded verbatim to codex, so all native subcommands (exec, resume, login, …) and flags (--model, --profile, --config, --cd, …) work as usual.

Authentication

Codex CLI supports two auth modes:

  • API key — export OPENAI_API_KEY in your shell or set it in .env.codex. The wrapper forwards it into the container.
  • ChatGPT sign-in — run codex login inside the container; the resulting ~/.codex/auth.json is persisted on the host and reused on every run.

Unlike Claude Code, Codex CLI keeps a single login per host: splitting state across multiple sessions would force you to log in again for each one. The wrapper therefore mounts ~/.codex-jail/ directly as /home/codex/.codex inside the container, so auth, config, conversation history and logs are shared across every workspace — the same way the native codex CLI behaves on your host.

Configuration: .env.codex

Drop a .env.codex file in your workspace and the wrapper loads it. Two categories of variables are recognised:

Script-level (consumed by codex.sh, not forwarded into the container):

Variable Default CLI override
CODEX_JAIL_IMAGE codex-cli --image
CODEX_JAIL_WORKSPACE /workspace --container-workdir
CODEX_JAIL_NETWORK (none) --network
CODEX_JAIL_USE_SSH 0 --with-ssh-agent
CODEX_JAIL_MOUNTS (none) --mount (repeats)
CODEX_JAIL_IGNORE .codexignore --ignore-file
CONTAINER_MAX_MEMORY host RAM --max-memory

Container-level (forwarded as env vars inside the container):

Variable Notes
OPENAI_API_KEY Codex API authentication
anything else Custom vars defined in .env.codex are forwarded

Precedence order: CLI flag → host shell env → .env.codex → built-in default.

Copy .env.example as a starting point:

cp .env.example .env.codex

.codexignore

To hide files or directories from the container, drop a .codexignore in the workspace root. Patterns are one per line, glob-style; # starts a comment.

# Secrets
*.pem
.env
**/*.key

# Whole directories (trailing slash)
secrets/
node_modules/

For each match the wrapper stacks a tmpfs (directories) or a read-only /dev/null (files) on top of the workspace bind mount. The host files are untouched; Codex just sees emptiness where they would be.

Mounts beyond your project

Only four host paths are exposed by default:

  • the workspace itself (read/write)
  • ~/.codex-jail//home/codex/.codex (read/write, UID-remapped)
  • the SSH agent socket → /ssh-agent (only with --with-ssh-agent)
  • anything you add via --mount or CODEX_JAIL_MOUNTS

Nothing else from the host is reachable.

Build manually

make build                # podman build -t codex-cli:latest .
podman build -t my-codex . # equivalent direct invocation

The CACHEBUST build arg forces npm to re-resolve @openai/codex, so a plain make build always picks up the latest published Codex CLI.

License

BSD 3-Clause — see COPYRIGHT.