ConnectOnionConnectOnion

codex

Drive OpenAI's Codex CLI via its native app-server protocol — session resume, live step streaming, and per-action approval.

Installation

Requires the codex CLI and Codex auth:

code
npm install -g @openai/codex codex login # or your usual Codex auth flow

Set $CODEX_CMD to override the binary path/command if needed.

Quick Start

main.py
from connectonion import Agent from connectonion.useful_tools import codex agent = Agent("architect", tools=[codex]) agent.input("Ask Codex to fix the failing tests in ./myrepo")

Why app-server

ConnectOnion drives Codex's built-in app-server (OpenAI's native JSON-RPC 2.0 protocol) directly from Python — our own client is the adapter, so the only dependency is the codex binary itself, no external Node adapter.

This gets you session + resume (thread/start, thread/resume), live streaming of Codex's inner steps, and per-action approval — the server asks before each sensitive step, which maps onto agent.io.request_approval.

API

main.py
codex( prompt: str, # Task for Codex, e.g. "fix the failing tests" session_id: str = "", # Thread id from a previous call, to resume it cwd: str = "", # Directory Codex works in (default: cwd) sandbox: str = "workspace-write", # "read-only" | "workspace-write" | "danger-full-access" model: str = "", # Codex model override (e.g. "gpt-5-codex"); empty = default timeout: int = 600, # Seconds before timeout approval: str = "manual", # "manual" (ask via agent.io) or "auto" (approve automatically) ) -> str # JSON envelope

With no frontend to ask, manual approval denies each request rather than escalating.

Return Value

A JSON string envelope:

code
{ "provider": "codex", "session_id": "<thread id>", "resumed": false, "last_message": "...", "usage": { /* token/cost info, if reported */ }, "exit_code": 0 // "error": "..." — present only when something went wrong }

Resuming a Session

main.py
import json from connectonion.useful_tools import codex result = json.loads(codex("Start refactoring the auth module")) session_id = result["session_id"] # Later, continue the same Codex thread result2 = json.loads(codex("Now add tests for it", session_id=session_id)) print(result2["resumed"]) # True

Approval Modes

ModeBehavior
manualDefault. Asks the human via agent.io, rendered as an approval card. With no frontend attached, requests are denied rather than escalated.
autoApproves every request automatically — no human in the loop.

Sandbox Levels

ValueMeaning
read-onlyCodex can inspect the codebase but not write to it
workspace-writeDefault. Codex can edit files inside the working directory
danger-full-accessNo sandbox restrictions — use with caution

Frontend Contract

Codex's inner steps are streamed as the same events the connection layer bundled in @connectonion/react already maps to chat items — tool_call (stable tool ID) and tool_result — so no frontend or SDK change is needed to render Codex activity.

Star us on GitHub

If ConnectOnion saves you time, a ⭐ goes a long way — and earns you a coffee chat with our founder.