How to Run a Ralph Loop With the Codex CLI
The ralph loop Codex setup is four moves: install Ralph into your project, log in to Codex once inside its sandbox, then run ./ralph.sh --agent codex. Ralph drives Codex through its non-interactive exec subcommand, hands it a fresh context window every iteration, and keeps re-running it against your task list until the work is done or you hit the iteration cap.
This is the full walkthrough, from an empty repo to a diff you review in the morning. If the loop itself is new to you, start with what the Ralph technique is. If you want the flag-level mechanics of the Codex backend, the companion piece is running the Codex CLI in a loop. This post is the brand-specific setup recipe.
What makes Codex different inside a Ralph loop?
Section titled “What makes Codex different inside a Ralph loop?”Codex is the one agent Ralph does not drive with a print flag. Claude and Cursor take a -p flag; Gemini and Copilot take -p after their separators; OpenCode gets a run subcommand. Codex gets exec, its non-interactive execution mode. You can see the exact shape in scripts/lib/agents.sh, where build_agent_command emits the Codex case as ... -- exec%s "$PROMPT_CONTENT".
That subcommand matters more than it looks. codex exec is the headless path: it reads a prompt, edits files, runs commands, prints a final message, and exits with a status code. No REPL, no approval prompt waiting on a human, no interactive session to resume. Exit is the whole contract, and exit is exactly what a loop needs. Each iteration spawns one codex exec, lets it finish one task, reads what it emitted, and starts the next pass clean.
Ralph supplies the three things a lone codex exec call cannot:
- A loop, so Codex gets another pass after every commit instead of stopping.
- Fresh context per iteration, so a long unattended run never rots into a confused, drifting session.
- A Docker sandbox boundary, so Codex can edit files and run shell commands in bypass-permissions mode without that blast radius reaching your real machine.
The state lives on disk (the task list, the logs, the git history), not in a chat transcript. That is what lets a stateless codex exec reorient on every pass and still make forward progress across dozens of iterations.
Step 1: Install Ralph
Section titled “Step 1: Install Ralph”Run the installer in your project root. It drops the ralph.sh script and the .agent/ directory into the repo.
npx @pageai/ralph-loopThe installer asks for your dev server URL and port and your default agent, then writes a default implementation-mode setup. Pick codex when prompted, or set it per run with --agent codex later. If the script is not already executable, fix that:
chmod +x ralph.shRalph runs each agent inside a Docker Sandbox, so install and sign in to Docker Sandbox first. See the Docker Sandboxes docs for the official setup flow. The loop calls the standalone sbx CLI under the hood, and the sandbox is what makes bypass-permissions mode safe.
Step 2: Log in to Codex inside the sandbox
Section titled “Step 2: Log in to Codex inside the sandbox”Codex runs inside an isolated sandbox, not on your host, so it needs credentials in that environment. Authenticate once with the login action:
./ralph.sh --login --agent codexRalph prints the login command for every supported agent, highlights the Codex one, and drops you into the sandbox shell. The command it runs to create the box looks like this:
sbx run --name ralph-codex-<project>-<hash8> codex .Inside the sandbox, authenticate Codex once. Run codex login and follow the prompt to connect your OpenAI account. If OAuth does not persist in the sandbox, the alternative is an OPENAI_API_KEY environment variable, which Docker Sandboxes forward when you create the box. The credential persists in that named sandbox, so later runs attach to the same box already logged in.
Each agent gets its own deterministic sandbox name, built from the agent slug, the project directory, and an 8-character hash of the absolute path:
ralph-codex-<project>-<hash8>Print the exact name for your project without starting a run:
./ralph.sh --print-name --agent codexIf your tasks run a dev server you want to reach from the host, publish the configured port to the Codex sandbox. The port comes from the dev-server URL you set during install:
./ralph.sh --ports --agent codexThat expands to an sbx ports call against the Codex sandbox, for example sbx ports ralph-codex-<project>-<hash8> --publish 3000:3000. Per-agent names keep state separate: your Codex sandbox and your Claude sandbox never share credentials or installed tools, so you can run both against the same repo without one clobbering the other.
Step 3: Create a PRD and task list
Section titled “Step 3: Create a PRD and task list”The loop executes a task list. It does not invent one. Before you run anything, turn your requirements into a PRD and a set of task specs with the prd-creator skill.
Open Codex (or any agent) in plan mode and prompt it with your requirements:
Use the prd-creator skill to help me create a PRD and task list for the below requirements.
An app is already set up with React, Tailwind CSS and TypeScript.
Requirements:- A SaaS product that helps users manage their finances.- Track income and expenses, create invoices, generate reports.- Use shadcn/ui for components and Supabase for the database.// etc.The skill writes .agent/prd/PRD.md, a short .agent/prd/SUMMARY.md, and per-task specs under .agent/tasks/, indexed by .agent/tasks.json. Review each task individually before you start. A clear task list with real acceptance criteria is the single biggest factor in whether the loop succeeds.
Step 4: Run the ralph loop codex command
Section titled “Step 4: Run the ralph loop codex command”With a task list in place and Codex authenticated, start the loop. Claude is the default agent, so name Codex explicitly:
# 10 iterations (the default)./ralph.sh --agent codex
# 50 iterations for a longer unattended run./ralph.sh --agent codex -n 50
# exactly one iteration, good for a smoke test./ralph.sh --agent codex --onceThe short form -a works too: ./ralph.sh -a codex -n 5. You can also cap iterations with --max-iterations 5. The count is a safety budget, not a target. The loop stops the moment the work is done.
Under the hood, Ralph builds a codex exec command and runs it inside the sandbox. For ./ralph.sh --agent codex, the expansion is:
sbx run --name ralph-codex-<project>-<hash8> codex . -- exec "$PROMPT_CONTENT"Read that right to left. "$PROMPT_CONTENT" is the contents of .agent/PROMPT.md, the instruction set for one pass. exec puts Codex in non-interactive mode. Everything before the second -- is the sandbox wrapper. That is the entire ralph loop codex command: one headless Codex run per iteration, no session state carried between passes.
Pick a model and reasoning effort
Section titled “Pick a model and reasoning effort”Model selection is where the Codex path earns its own section, because Codex is the CLI where Ralph documents real model flags. Everything to the right of Ralph’s own -- separator is forwarded straight to Codex, inserted right after exec. So this:
./ralph.sh --agent codex -- --model gpt-5.5expands to:
sbx run --name ralph-codex-<project>-<hash8> codex . -- exec --model gpt-5.5 "$PROMPT_CONTENT"And the codex-reasoning variant works the same way:
./ralph.sh --agent codex -- --model gpt-5.3-codexwhich expands to:
sbx run --name ralph-codex-<project>-<hash8> codex . -- exec --model gpt-5.3-codex "$PROMPT_CONTENT"The rule to remember: everything left of -- configures Ralph (agent, iteration count, login), and everything right of -- configures Codex, landing right after exec. Pick the model that fits the run. A heavier reasoning model is worth the token cost on a gnarly refactor where a wrong turn compounds across iterations. A faster model is fine for mechanical task lists where each step is well specified. A practical full command for an overnight run:
./ralph.sh --agent codex -n 50 -- --model gpt-5.3-codexDo not guess at other model identifiers. Use the ones your account and CLI version actually expose, and confirm them inside the sandbox before committing to a long run. The two above (gpt-5.5 and gpt-5.3-codex) are the ones Ralph’s own docs show, so they are safe starting points.
What happens each iteration
Section titled “What happens each iteration”Every pass is mechanical and identical. Codex reorients from disk, does one task, proves it works, and commits.
- Find the highest-priority incomplete task in
.agent/tasks.json. - Work the steps in
.agent/tasks/TASK-{ID}.json. - Run tests, linting, and type checking.
- Complete the task, take a screenshot, update the task status, and commit.
- Repeat until all tasks pass or the iteration cap is reached.
The key detail is that each iteration spawns a fresh codex exec with a clean context window. Codex does not carry an hours-long transcript from one task to the next. It reads the current state from disk, does one task, and exits. This is why the loop deliberately does not resume a prior Codex session: continuity is a liability here, not a feature.
flowchart TD
Start(["./ralph.sh --agent codex -n 50"]) --> Pick["Pick top task from .agent/tasks.json"]
Pick --> Spawn["sbx run codex . -- exec (fresh context)"]
Spawn --> Work["codex exec reads state, edits files, runs commands"]
Work --> Verify["Run tests, lint, type check, screenshot"]
Verify --> Commit["Commit and update task status"]
Commit --> Check{"Promise tag emitted?"}
Check -->|"none"| Pick
Check -->|"COMPLETE"| Done(["exit 0, all tasks done"])
Check -->|"BLOCKED or DECIDE"| Stop(["exit 2 or 3, wants a human"])
The filesystem and git history are the memory layer. Progress lives in .agent/tasks.json, .agent/logs/LOG.md, the per-task specs, and the git log, not in a chat transcript. The prompt that drives every pass lives in .agent/PROMPT.md, which defaults to implementation mode and can be swapped for refactor, review, or test mode.
One rule keeps the whole thing reliable: one task per invocation. Codex completes exactly one task, commits, and stops. It never batches several tasks into a single iteration, which is what keeps each commit small and each diff reviewable.
How the loop knows when to stop
Section titled “How the loop knows when to stop”A loop that never ends is a money fire, so Ralph stops on an explicit signal rather than a guess. Codex emits a semantic promise tag in its final message and Ralph reads it:
<promise>COMPLETE</promise>means every task is finished.<promise>BLOCKED:reason</promise>means the agent needs human help.<promise>DECIDE:question</promise>means it needs a decision you have to make.
Those map to exit codes, which is what makes the loop scriptable:
./ralph.sh --agent codex -n 50echo $? # 0 COMPLETE, 1 MAX_ITERATIONS, 2 BLOCKED, 3 DECIDEExit code 1 is not a failure. It means the loop spent its iteration budget with work still pending, which is exactly what a safety cap is for. If Codex is not authenticated when the loop starts, Ralph detects the auth failure, stops, and tells you to run codex login, so it never thrashes on a box that can never make progress.
Steer, debug, and review
Section titled “Steer, debug, and review”Three things keep a long Codex run under control.
Steer without stopping
Section titled “Steer without stopping”If you notice Codex heading the wrong way, you do not have to kill the loop. Edit .agent/STEERING.md while it runs. Codex checks that file on each pass and handles the critical work there before resuming the normal task order. That is steering, not stopping, and it keeps momentum while you correct course.
Get inside the sandbox
Section titled “Get inside the sandbox”The sandbox is a normal container you can poke at. List what exists, then open a shell in the Codex box:
sbx lssbx exec -it ralph-codex-<project>-<hash8> bashFrom there you can re-run a failing test by hand, run codex interactively to confirm auth, or read .agent/logs/LOG.md and the per-iteration logs in .agent/history/. To reattach to the running box directly, use sbx run ralph-codex-<project>-<hash8> with no agent slug and no path. When an install fails, the deny-by-default network is usually the cause. Allow the domain it needs:
sbx policy allow network ralph-codex-<project>-<hash8> registry.npmjs.orgThat is a feature, not a bug. Codex installs what the task needs without a path to exfiltrate your source. If you want the broader argument for why the sandbox is the boundary, running an AI coding agent overnight covers the safety model end to end.
Review the diff in the morning
Section titled “Review the diff in the morning”Because every task is committed separately, the morning review is a git review, not an archaeology dig:
git log --onelinegit diff main...HEADYou read the commits in order, eyeball the screenshots Codex captured, and accept or revert. A single bad task is one revert, not a tangled mess. The verification stack Ralph assumes (Playwright for end-to-end, Vitest for unit tests, TypeScript for types, ESLint for lint, Prettier for format) is what gives each commit evidence behind it. The repo mantra holds: if you did not test it, it did not work.
Should you use Codex or another agent?
Section titled “Should you use Codex or another agent?”Ralph is agent agnostic. The supported agents are claude (default), codex, copilot, cursor, gemini, and opencode, and switching is a single flag. The loop machinery is identical across all of them. What sets Codex apart is the interface: it is the one agent Ralph drives through the exec subcommand rather than a print flag, and the one where model selection is a documented, first-class part of the command. If you already run OpenAI models and want explicit control over which model and how much reasoning each run gets, Codex is a natural fit. If you want the pure shell mechanics behind all of this, read how Ralph is a shell script, and for the Cursor equivalent of this walkthrough, see running a Ralph loop with the Cursor CLI.
A real Codex loop, start to finish, is four commands:
# 1. install Ralph and scaffoldingnpx @pageai/ralph-loop
# 2. authenticate once (creates the sandbox, you log in inside it)./ralph.sh --login --agent codex
# 3. smoke test a single pass./ralph.sh --agent codex --once
# 4. run the loop for real with a model./ralph.sh --agent codex -n 50 -- --model gpt-5.3-codexDefine your tasks in .agent/tasks.json, write a clear .agent/PROMPT.md, pick a model, start the loop, and read the commits in the morning. The Ralph technique itself, fresh context plus disk-backed memory plus an explicit stop signal, was popularized by Geoffrey Huntley in his original writeup, and Codex slots into it cleanly through one non-interactive subcommand.
Frequently asked questions
How do I run a Ralph loop with the Codex CLI?
Install Ralph with npx @pageai/ralph-loop, create a task list, log in with ./ralph.sh --login --agent codex, then run ./ralph.sh --agent codex. Ralph drives Codex through its non-interactive exec subcommand inside a Docker sandbox, starts a fresh context each iteration, and repeats until every task in .agent/tasks.json is done or the iteration cap is reached.
Why does Ralph use codex exec instead of a print flag?
exec is Codex CLI non-interactive mode. It reads a prompt, edits files, runs commands, prints a final message, and exits with a status code, with no REPL or approval prompt waiting on a human. In scripts/lib/agents.sh the Codex case expands to sbx run codex . -- exec "$PROMPT_CONTENT", which is the exact behavior a loop needs.
How do I pass a model to Codex through Ralph?
Put it after the -- separator. Anything to the right of -- is forwarded to Codex and inserted right after exec, so ./ralph.sh --agent codex -- --model gpt-5.5 runs codex exec with that model and the Ralph prompt. The docs also show ./ralph.sh --agent codex -- --model gpt-5.3-codex. Confirm the exact identifiers your account exposes before a long run.
How do I log in to Codex for the loop?
Run ./ralph.sh --login --agent codex. It drops you into the sandbox shell where you run codex login, or you can set an OPENAI_API_KEY environment variable that Docker Sandboxes forwards when the box is created. The credential persists in the sandbox named ralph-codex-<project>-<hash8>, so future runs attach already authenticated.
What does the ralph loop codex exit code mean?
Codex emits a promise tag that Ralph maps to an exit code: 0 for COMPLETE when all tasks finish, 1 for MAX_ITERATIONS when the budget runs out with work pending, 2 for BLOCKED when it needs help, and 3 for DECIDE when it needs a decision. Exit code 1 is not a failure, it just means the safety cap did its job.