Raised: $0
0% of monthly goal Help us cross the finish line!
Goal: $12,000
Raised: $0 Goal: $12,000
0% of monthly goal Help us cross the finish line!
Sponsor DDEV

If you find this add-on useful, please star it on GitHub — stars show appreciation and help maintainers know their work matters.

add-on registry tests last commit release

DDEV Codex

This add-on installs the OpenAI Codex CLI in a dedicated DDEV sidecar. The sidecar uses the project’s built web image, so it has the same PHP, Composer, Node.js, and project-specific tools as the web container. It supports AMD64 and ARM64 hosts.

AI Usage Disclosure

This ddev addon has been written with codex assistance.

Installation

ddev add-on get ptmkenny/ddev-codex
ddev restart

Commit the generated files under .ddev, including .ddev/codex/.gitignore. Codex state and credentials within .ddev/codex/ will be ignored.

Authentication

If you have a ChatGPT subscription, enable device code authorization in your ChatGPT security settings and run:

ddev codex login --device-auth

Open the displayed URL in a browser and enter the one-time code. Codex stores the resulting credentials in .ddev/codex/, where they persist across DDEV restarts.

To use an API key instead, pipe it to Codex from your host environment:

printf '%s' "$OPENAI_API_KEY" | ddev codex login --with-api-key

Treat .ddev/codex/auth.json as a secret. Do not commit or share it.

Usage

# Start an interactive session in the project root.
ddev codex

# Show CLI help or the installed version.
ddev codex --help
ddev codex --version

# Run a prompt directly.
ddev codex "explain this project"

The sidecar starts with the project and mounts the same project filesystem as the web container. This includes DDEV’s Mutagen volume when Mutagen is enabled, so Codex does not use a second, slower project bind mount. Commands such as PHPCS, PHPStan, Composer, and Drush run directly in the sidecar:

ddev exec --service codex vendor/bin/phpcs
ddev exec --service codex vendor/bin/phpstan analyse
ddev exec --service codex drush status

The add-on also installs Bubblewrap and Python Pillow in the shared project image. Pillow supports Codex image-generation helper scripts that need the PIL Python package.

Codex version

The latest Codex release is installed by default. To pin a release, create .ddev/.env.codex:

CODEX_VERSION=0.152.1

Then rebuild the project image without its Docker cache:

ddev restart --no-cache

Use the same command to update a project that follows latest.

Linux sandbox inside DDEV

Codex’s Linux sandbox uses Bubblewrap and nested user and mount namespaces. Docker’s default seccomp, AppArmor, and protected-system-path settings block operations Bubblewrap needs. Only the Codex sidecar disables those three outer restrictions with seccomp=unconfined, apparmor=unconfined, and systempaths=unconfined. The web and database containers retain their normal Docker security profiles. This is the same three-option configuration Moby documents for a rootless sandbox running inside Docker.

The sidecar also drops all Linux capabilities and enables no-new-privileges. It is not privileged and does not mount the Docker socket or DDEV SSH agent. Codex can modify the project and connect to DDEV services by their Compose names, such as web and db, but it cannot use Docker to inspect or execute commands inside those containers.

systempaths=unconfined removes Docker’s masks from sensitive /proc and /sys paths inside the sidecar. This is necessary for Bubblewrap to create its inner mount layout, but it weakens the sidecar’s outer Docker boundary. Keep the sidecar non-root and do not add capabilities or host-level mounts.

DDEV injects variables from .ddev/.env and .ddev/.env.local into every project service, including this sidecar. Put web-only secrets in a targeted file such as .ddev/.env.web.local when Codex should not receive them.

The idle sidecar runs only a keepalive process. It reuses the already-built web image and DDEV project mount, so the steady-state CPU impact is negligible and the main additional cost is one small container process and its writable layer.

Optional SSH agent access

SSH agent access is disabled by default. To opt in, add .ddev/docker-compose.codex-ssh-agent.yaml:

services:
  codex:
    environment:
      - SSH_AUTH_SOCK=/home/.ssh-agent/socket
    volumes:
      - ddev-ssh-agent_socket_dir:/home/.ssh-agent

volumes:
  ddev-ssh-agent_socket_dir:
    external: true

Removal

ddev add-on remove codex

DDEV preserves .ddev/codex/ when it contains Codex state. Remove that directory manually if you also want to delete the stored credentials and configuration.

Credits

This add-on was inspired by Gonzalo2683/ddev-codex. Patrick Kenny maintains this implementation at ptmkenny/ddev-codex.

License

Apache License 2.0. See LICENSE.

If you find this add-on useful, please star it on GitHub — stars show appreciation and help maintainers know their work matters.