Deterministic multi-agent orchestrator for OpenAI Codex — TS port of the Python codex_workflow.py /
codex_patterns.py kit, on the Codex SDK, plus an in-session MCP-server front door.
- Structured token usage from the SDK (
turn.completed.usage) instead of scraping--jsonfooters. - Resume via a read-only content-hash cache (
resumeThreadavailable for explicit continuation). - MCP-server front door (
src/mcpServer.ts): register it in~/.codex/config.tomland the in-session model callsultracode(task, n?)as a tool — the server (a sibling of the harness, outside the per-command sandbox, so it keeps network) deterministically fans out N workers. This is the move that makes deterministic fan-out an in-session primitive (source-verified againstcodex-rs/rmcp-client/src/stdio_server_launcher.rs).
cd ts
npm install
npm run smoke:esm # runtime ESM import sanity (beyond tsc)
npm run typecheck # tsc --noEmit
npm test # vitest — offline suite (SDK adapter stubbed; no network/tokens) — 18/18
npx tsx src/preflight.ts # CodexEnv probe — REQUIRED before live runs (needs codex auth + tokens)
npm run live # live engine smoke: parallel agents + worktree writer (needs auth + tokens)
npm run mcp:call # drive the ultracode MCP tool end-to-end (real fan-out; needs auth + tokens)preflight.ts is the gate for the unverified SDK↔CLI contract: (1) thread.id resolves to a resumable
rollout, (2) mcp_servers={} override + --output-schema are honored, (3) turn.usage.output_tokens is
readable, (4) the effort override neutralizes config.toml. Do not trust resume/budget until it passes.
# ~/.codex/config.toml (get confirmation before editing this file)
[mcp_servers.ultracode]
command = "/opt/homebrew/bin/node" # absolute, so it launches regardless of curated PATH
args = ["/abs/path/to/ts/dist/mcpServer.js"] # after `npm run build`
[mcp_servers.ultracode.env] # launcher does env_clear — auth/PATH MUST be provided
HOME = "/Users/you"
CODEX_HOME = "/Users/you/.codex" # so the server + its child codex runs find auth.json
PATH = "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin"Then, in any codex session: the model can call ultracode("…", 16) / ultracode_review([...]).
Caveats (baked into the code): the tool is non-interactive (children run read-only / edit-only — no
shell approval, or headless codex exec stalls, issue #24135); fan-out is bounded (ULTRACODE_MAX_FANOUT,
default 32); children run MCP-clean; live progress is approximated (use workflow_status(run_id)).
CODEX_WF_MODEL (gpt-5.5) · CODEX_WF_EFFORT (medium) · CODEX_WF_CONCURRENCY (min(16,cores-2)) ·
CODEX_WF_CWD · CODEX_WF_BUDGET (output-token ceiling; unset = unlimited) · CODEX_WF_EST_TOKENS ·
CODEX_WF_MCP_CLEAN (1) · CODEX_WF_ARGS (JSON).
src/codexClient.ts is the only SDK-touching file. Confirmed live: Turn = { items, finalResponse, usage },
Usage.output_tokens reads, thread.id IS the resume key (rollout round-trips), and per-thread config is
camelCase ThreadOptions (model / sandboxMode / modelReasoningEffort / workingDirectory /
skipGitRepoCheck) — not a snake_case config object. Pin @openai/codex-sdk to a version whose bundled
codex matches your resume target (version drift is real: this machine had a 0.125 PATH binary with sessions
written by 0.117→0.140).
npm install + tsc --noEmit + 18/18 offline vitest + live preflight 4/4 + live engine smoke
(parallel + worktree, no leak) + MCP stdio handshake + MCP tool fan-out end-to-end (one
ultracode(n=2) call → 2 child codex workers that retained network → synthesis + ledger). In-session via
codex exec, codex loads the server and the model invokes the tool; headless completion is gated by the
account's cloud OnRequest approval (issue #24135), clearable by a single interactive approval.