Codex¶
Codex is an AI coding assistant provided by OpenAI. It can inspect and modify files, execute commands, and work with existing codebases from the terminal.
On SAV infrastructure, Codex runs in a Singularity/Apptainer container on an HPC login node. It connects directly to OpenAI; no vLLM server or SSH tunnel is required.
Quickstart¶
From the directory containing your project, run:
cd ~/my-project
~/llm/codex.sh
The launcher displays:
Codex session:
1) Continue last session
2) Start new session
3) Select previous session
4) Exit
Select [1]:
Press Enter to resume the latest session, or select another option.
Launcher¶
Save the launcher shown below as ~/llm/codex.sh and make it executable:
chmod +x ~/llm/codex.sh
The launcher uses two host account files to resolve your UID and group inside the container. Create them once:
mkdir -p ~/llm
getent passwd root "$USER" > ~/llm/.container_passwd
getent group root "$(id -gn)" > ~/llm/.container_group
Regenerate these files if your account or primary group changes. Do not run the launcher as root unless you deliberately want root's authentication and session history.
Authentication¶
Codex connects to OpenAI. Authenticate using the method supported by your
Codex installation and account, typically by starting Codex and following
its sign-in instructions. The launcher binds $HOME, so configuration and
session data persist between runs. No local vLLM API key is required.
Usage¶
codex.sh [WORKSPACE] [MODE] [-B HOST[:CONTAINER]] [-- CODEX_ARGS...]
WORKSPACE Working directory (default: current directory)
MODE --continue, --new, --resume, or --list
-B, --bind Additional bind mount (repeatable)
-- ARGS Additional arguments passed to Codex
Examples:
# Open the menu in the current directory.
~/llm/codex.sh
# Work in another directory and start a new session.
~/llm/codex.sh /myproject/path --new
# Resume the most recent session.
~/llm/codex.sh --continue
# Open the session selector.
~/llm/codex.sh --resume
# Mount additional directories.
~/llm/codex.sh /myproject/path \
-B /project/<account_ID>:/project/<account_ID> \
-B /scratch/<account_ID>:/scratch/<account_ID>
# Display the Codex CLI help.
~/llm/codex.sh --new -- --help
Session modes¶
| Launcher mode | Codex arguments | Effect |
|---|---|---|
--continue |
--no-daemon resume --last |
Resume the latest session |
--new |
--no-daemon |
Start a new session |
--resume |
--no-daemon resume |
Open the session selector |
--list |
--no-daemon resume |
Alias for the session selector |
| (none) | Interactive menu | Prompt for a mode |
--continue and --resume are launcher options, not native Codex
options. The native Codex session interface uses the resume subcommand.
The --no-daemon option is used because some containerized installations
lack the complete background-server package. Check codex --help and
codex resume --help if your installed version behaves differently.
The launcher¶
The script checks the image and workspace, parses session options and additional binds, loads Singularity where necessary, and launches Codex with the selected arguments. The container image path and Slurm bind path can be configured without modifying the script.
~/llm/codex.sh
#!/bin/bash
set -euo pipefail
# ----------------------------------------------------------------------
# Configuration
# ----------------------------------------------------------------------
CODEX_SIF="${CLAUDE_SIF:-/storage-apps/containers/vllm/x86_64/Claude_code_x86_64_Nov2026_perun.sif}" # Perun
#CODEX_SIF="${CLAUDE_SIF:-/apps/images/vllm/x86_64/Claude_code_x86_64_Nov2026_devana.sif}" # Devana
if [[ -z "$CODEX_SIF" || ! -f "$CODEX_SIF" ]]; then
echo "ERROR: CODEX_SIF is not set or the image does not exist." >&2
echo "Example: export CODEX_SIF=/path/to/Codex.sif" >&2
exit 1
fi
USER_HOME="$HOME"
USER_LLM_DIR="$HOME/llm"
WORKSPACE="$PWD"
WORKSPACE_SET=0
MODE=""
EXTRA_ARGS=()
EXTRA_BINDS=()
# ----------------------------------------------------------------------
# Usage
# ----------------------------------------------------------------------
usage() {
cat <<EOF
Usage:
$(basename "$0") [WORKSPACE] [MODE] [OPTIONS] [-- CODEX_ARGS...]
Modes:
--continue Continue the last session
--new Start a new session
--resume Select a previous session
--list Open the session picker
Options:
-B, --bind HOST[:CONTAINER]
Add an additional bind mount (repeatable)
-h, --help Show this help
Examples:
$(basename "$0")
$(basename "$0") /project/myproject
$(basename "$0") --continue
$(basename "$0") /project/myproject --new
$(basename "$0") -B /data:/data
$(basename "$0") /project/myproject -B /data:/data -- --model gpt-5.1-codex
Default bind mounts:
\$HOME:\$HOME
/project/p2075-26-2:/project/p2075-26-2
/run/munge:/run/munge
/var/spool/slurmd/conf-cache:/etc/slurm
\$HOME/llm/.container_passwd:/etc/passwd
\$HOME/llm/.container_group:/etc/group
EOF
}
# ----------------------------------------------------------------------
# Parse arguments
# ----------------------------------------------------------------------
while [[ $# -gt 0 ]]; do
case "$1" in
--continue|--new|--resume|--list)
MODE="$1"
shift
;;
-B|--bind)
if [[ $# -lt 2 ]]; then
echo "ERROR: $1 requires a bind specification." >&2
exit 1
fi
EXTRA_BINDS+=("$2")
shift 2
;;
--)
shift
EXTRA_ARGS+=("$@")
break
;;
-h|--help)
usage
exit 0
;;
-*)
echo "ERROR: Unknown option: $1" >&2
usage >&2
exit 1
;;
*)
if [[ "$WORKSPACE_SET" -eq 0 ]]; then
WORKSPACE="$1"
WORKSPACE_SET=1
else
echo "ERROR: Unexpected argument: $1" >&2
usage >&2
exit 1
fi
shift
;;
esac
done
# ----------------------------------------------------------------------
# Validate workspace
# ----------------------------------------------------------------------
WORKSPACE="$(realpath "$WORKSPACE")"
if [[ ! -d "$WORKSPACE" ]]; then
echo "ERROR: Workspace does not exist: $WORKSPACE" >&2
exit 1
fi
# ----------------------------------------------------------------------
# Interactive session menu
# ----------------------------------------------------------------------
case "$MODE" in
--continue)
CODEX_ARGS=(--no-daemon resume --last)
;;
--new)
CODEX_ARGS=(--no-daemon)
;;
--resume|--list)
CODEX_ARGS=(--no-daemon resume)
;;
"")
if [[ ! -t 0 ]]; then
echo "Not a terminal. Pass --continue, --new," >&2
echo "--resume or --list explicitly." >&2
exit 1
fi
echo
echo "Codex session:"
echo
echo " 1) Continue last session"
echo " 2) Start new session"
echo " 3) Select previous session"
echo " 4) List sessions"
echo " 5) Exit"
echo
read -r -p "Select [1]: " CHOICE || CHOICE=1
# Pressing Enter selects the default.
CHOICE=${CHOICE:-1}
case "$CHOICE" in
1)
CODEX_ARGS=(--no-daemon resume --last)
;;
2)
CODEX_ARGS=(--no-daemon)
;;
3|4)
CODEX_ARGS=(--no-daemon resume)
;;
5)
exit 0
;;
*)
echo "Invalid selection." >&2
exit 1
;;
esac
;;
*)
echo "Unknown option: $MODE" >&2
usage >&2
exit 1
;;
esac
# Append additional Codex arguments.
CODEX_ARGS+=("${EXTRA_ARGS[@]}")
# ----------------------------------------------------------------------
# Default bind mounts
# ----------------------------------------------------------------------
BINDS=(
"$WORKSPACE:$WORKSPACE"
"$USER_HOME:$USER_HOME"
"/project/p2075-26-2:/project/p2075-26-2"
"/run/munge:/run/munge"
"/var/spool/slurmd/conf-cache:/etc/slurm"
"$USER_LLM_DIR/.container_passwd:/etc/passwd"
"$USER_LLM_DIR/.container_group:/etc/group"
)
# Append user-defined bind mounts.
for bind in "${EXTRA_BINDS[@]}"; do
BINDS+=("$bind")
done
# ----------------------------------------------------------------------
# Load Singularity
# ----------------------------------------------------------------------
if command -v module >/dev/null 2>&1; then
module load singularity
fi
if ! command -v singularity >/dev/null 2>&1; then
echo "ERROR: singularity command not found." >&2
exit 1
fi
# Check architecture.
if [[ "$(uname -m)" != "x86_64" ]]; then
echo "ERROR: This Codex image requires x86_64." >&2
exit 1
fi
# ----------------------------------------------------------------------
# Build bind arguments
# ----------------------------------------------------------------------
SINGULARITY_BINDS=()
for bind in "${BINDS[@]}"; do
SINGULARITY_BINDS+=(--bind "$bind")
done
# ----------------------------------------------------------------------
# Launch Codex
# ----------------------------------------------------------------------
singularity exec \
"${SINGULARITY_BINDS[@]}" \
--pwd "$WORKSPACE" \
--env "PATH=/usr/local/bin:/opt/agent_env/bin:/opt/slurm/bin:/opt/slurm/sbin:$HOME/.local/bin:/usr/bin:/bin" \
"$CODEX_SIF" \
bash -lc 'exec codex "$@"' -- "${CODEX_ARGS[@]}"
Devana slurm bind
On devana slurm needs to be bind followingly -- bind /etc/slurm:/etc/slurm &
--env "PATH=/usr/local/bin:/opt/agent_env/bin:$HOME/.local/bin:/usr/bin:/bin"
Running agents responsibly¶
Codex can execute commands and modify files. Commands launched directly by the agent run on the login node, not on a compute node. Submit computationally intensive builds, tests, and simulations through Slurm.
For example, instruct the agent:
Compile the software and run its test suite. Submit the build and tests
through Slurm to the CPU partition using the appropriate project account.
Check the job status and report the output.
Compute allocation
Codex may submit jobs that consume your project's allocation. Specify
the account, partition, resource requirements, and walltime. Review
running jobs using squeue -u "$USER".
File modifications
Codex edits real files. Work inside the intended project directory, keep changes under version control, and review modifications before committing or executing generated code.
Bind mounts¶
The launcher binds the workspace and home directory. It also binds available Munge and Slurm resources and the optional host account files.
| Bind | Purpose |
|---|---|
$WORKSPACE:$WORKSPACE |
Access to the project directory |
$HOME:$HOME |
Persistent authentication, configuration, and sessions |
/run/munge:/run/munge |
Munge authentication socket directory |
$SLURM_CONF_DIR:/etc/slurm |
Slurm client configuration |
.container_passwd:/etc/passwd |
Host account resolution |
.container_group:/etc/group |
Host group resolution |
Additional bind mounts can be supplied with repeated -B options:
~/llm/codex.sh /myproject/path \
-B /project/<account_ID>:/project/<account_ID> \
-B /scratch/<account_ID>:/scratch/<account_ID>
The source paths must exist and be accessible on the host. Binding a workspace does not automatically expose other directories outside it.
Troubleshooting¶
Codex image not found
Check the configured path:
printf '%s\n' "$CODEX_SIF"
ls -lh "$CODEX_SIF"
If CODEX_SIF is unset, export the image path as described above.
unexpected argument '--continue' found¶
--continue is not a native Codex option. Use the launcher option
--continue, which translates to codex --no-daemon resume --last.
Do not pass --continue directly to the Codex executable.
`this CLI has no complete local package`
Some container images contain a CLI that cannot start its background
server. The installed CLI may recommend --no-daemon. The launcher
uses this option for new and resumed sessions. If it still fails,
inspect the installation or rebuild the image with a complete CLI.
Check the installed command-line interface:
apptainer exec "$CODEX_SIF" codex --help
apptainer exec "$CODEX_SIF" codex resume --help
`codex: command not found`
Inspect the executable inside the container:
apptainer exec "$CODEX_SIF" sh -c 'command -v codex'
If the executable is elsewhere, adjust the container PATH or the
final command in the launcher.
Slurm commands fail inside the container
Check the resources on the host:
ls -ld /run/munge "$SLURM_CONF_DIR"
ls -l ~/llm/.container_passwd ~/llm/.container_group
Verify that the Slurm client is available in the container:
apptainer exec \
--bind /run/munge:/run/munge \
--bind "$SLURM_CONF_DIR:/etc/slurm" \
--env 'PATH=/opt/slurm/bin:/opt/slurm/sbin:/usr/bin:/bin' \
"$CODEX_SIF" squeue -u "$USER"
| Symptom | Possible cause |
|---|---|
squeue: command not found |
Slurm binaries absent from PATH |
| Invalid user/group | Missing or outdated account bind files |
| Munge authentication error | Munge socket unavailable or not mounted |
| Unable to contact controller | Wrong Slurm configuration or connectivity issue |
| Bind mount error | Source path missing or inaccessible |
Codex cannot access project files
Check directory permissions and pass additional paths with -B:
ls -ld "$PWD"
~/llm/codex.sh "$PWD" -B /project/shared:/project/shared
A session cannot be resumed
Session history is stored under the user's home directory. Use the same Unix account and home directory as when the session was created. To select a previous session, run:
~/llm/codex.sh --resume
A session created as a regular user will not necessarily be visible when the launcher is run as root.
Reference¶
| Task | Command |
|---|---|
| Interactive menu | ~/llm/codex.sh |
| Continue last session | ~/llm/codex.sh --continue |
| Start new session | ~/llm/codex.sh --new |
| Select previous session | ~/llm/codex.sh --resume |
| Session selector alias | ~/llm/codex.sh --list |
| Another workspace | ~/llm/codex.sh ~/my-project |
| Additional bind mount | ~/llm/codex.sh -B /data:/data |
| Codex help | ~/llm/codex.sh --new -- --help |
| Variable | Purpose |
|---|---|
CODEX_SIF |
Path to the Codex Singularity image |
SLURM_CONF_DIR |
Host Slurm configuration directory |