Files
ddev-claude-cli/codex-cli/install.sh
T
2026-10-16 15:10:26 +02:00

82 lines
3.5 KiB
Bash
Executable File

#!/usr/bin/env bash
#ddev-generated
set -euo pipefail
# All Codex CLI state is stored under .ddev/codex-cli so it survives container
# rebuilds without being committed to the project repository.
PERSIST_BASE="${DDEV_APPROOT}/.ddev/codex-cli"
PERSIST_HOME="${PERSIST_BASE}/home" # replaces $HOME inside the container
PERSIST_CONFIG_HOME="${PERSIST_BASE}/config" # XDG_CONFIG_HOME (e.g. ~/.config)
PERSIST_DATA_HOME="${PERSIST_BASE}/data" # XDG_DATA_HOME (e.g. ~/.local/share)
PERSIST_STATE_HOME="${PERSIST_BASE}/state" # XDG_STATE_HOME (e.g. ~/.local/state)
PERSIST_BIN_DIR="${PERSIST_BASE}/bin" # directory that holds the codex binary
PERSIST_BIN="${PERSIST_BIN_DIR}/codex" # full path to the codex executable
PERSIST_GITIGNORE_GLOBAL="${PERSIST_HOME}/.gitignore_global" # mirrors $HOME/.gitignore_global
# Capture the container's original HOME before we override it below, so we can
# seed the persisted gitignore from the container image on first run.
CONTAINER_HOME="${HOME:?HOME must be set}"
CONTAINER_GITIGNORE_GLOBAL="${CONTAINER_HOME}/.gitignore_global"
# Ensure all persistence directories exist.
mkdir -p \
"${PERSIST_HOME}" \
"${PERSIST_CONFIG_HOME}" \
"${PERSIST_DATA_HOME}" \
"${PERSIST_STATE_HOME}" \
"${PERSIST_BIN_DIR}"
# Seed the persisted gitignore from the container image on first run only.
if [ -f "${CONTAINER_GITIGNORE_GLOBAL}" ] && [ ! -f "${PERSIST_GITIGNORE_GLOBAL}" ]; then
cp -f "${CONTAINER_GITIGNORE_GLOBAL}" "${PERSIST_GITIGNORE_GLOBAL}"
fi
# Codex stores its standalone package tree under $HOME/.codex and links
# $CODEX_INSTALL_DIR/codex into that tree. Point HOME there before any install
# or health check so package data survives container restarts.
export HOME="${PERSIST_HOME}"
export CODEX_HOME="${PERSIST_HOME}/.codex"
export XDG_CONFIG_HOME="${PERSIST_CONFIG_HOME}"
export XDG_DATA_HOME="${PERSIST_DATA_HOME}"
export XDG_STATE_HOME="${PERSIST_STATE_HOME}"
export PATH="${PERSIST_BIN_DIR}:${HOME}/.local/bin:${PATH}"
# If a persisted binary exists but fails to run (e.g. wrong architecture after
# a host OS change), remove it so the install step below fetches a fresh copy.
if [ -x "${PERSIST_BIN}" ] && ! "${PERSIST_BIN}" --version >/dev/null 2>&1; then
echo "Persisted Codex CLI binary is not runnable, reinstalling ..."
rm -f "${PERSIST_BIN}"
fi
# Download and install the Codex CLI into the persisted bin directory.
if [ ! -x "${PERSIST_BIN}" ]; then
echo "Installing Codex CLI ..."
export CODEX_INSTALL_DIR="${PERSIST_BIN_DIR}"
export CODEX_NON_INTERACTIVE=1
curl -fsSL https://github.com/openai/codex/releases/latest/download/install.sh | sh
fi
# Verify the binary is present after installation.
if [ ! -x "${PERSIST_BIN}" ]; then
echo "Codex CLI installation completed but no executable was found at ${PERSIST_BIN}." >&2
exit 1
fi
# Point git's global excludes file at the persisted copy when available,
# so git inside the container respects user-defined ignore patterns.
if command -v git >/dev/null 2>&1 && [ -f "${PERSIST_GITIGNORE_GLOBAL}" ]; then
CURRENT_EXCLUDESFILE="$(git config --global --get core.excludesfile || true)"
if [ "${CURRENT_EXCLUDESFILE}" != "${PERSIST_GITIGNORE_GLOBAL}" ]; then
git config --global core.excludesfile "${PERSIST_GITIGNORE_GLOBAL}"
fi
fi
# Shared with the Claude side: keeps the add-on's artifacts out of the project's git
# even when only the codex installer runs.
GIT_EXCLUDE="${DDEV_APPROOT}/.ddev/claude-code/git-exclude.sh"
if [ -x "${GIT_EXCLUDE}" ]; then
"${GIT_EXCLUDE}" || true
fi
echo "Codex CLI version: $("${PERSIST_BIN}" --version)"