Your codex exec is wasting ~900 ms per turn. I measured where. A developer rebuilt the JavaScript harness of OpenAI's Codex CLI on Bun and found that a telemetry exporter adds about 900 ms per turn, which can be disabled with a config line. The persistent-process design delivers significant speedups on both Bun and Node 22, and the toolchain benefits include faster test startup and install times. I spent a weekend rebuilding the JavaScript harness of OpenAI's Codex CLI on Bun. I expected a runtime story. I got an architecture story — and one config line you can use today without touching my fork. Codex is a Rust engine with a thin JavaScript layer on top: an npm launcher, a TypeScript SDK, and a pnpm/jest/tsup toolchain. I swapped that layer to Bun, added a client that keeps one codex app-server process alive instead of spawning a fresh process per turn, and measured everything with hyperfine and mitata, p50 and p99. Ten short turns, same Rust engine, wall clock on my machine: 10 turns total telemetry on telemetry off process per turn. 12.5 s 0.76 s one process, kept up 1.6 s 0.31 s Read it down: the persistent-process design wins in both columns. Read it across: something is eating a second per process. The surprise Every release build of codex enables a telemetry exporter that debug builds silently disable. It flushes metrics over HTTPS while the process shuts down. Your answer prints, the turn is done — and the process lives ~900 ms longer to upload metrics. Spawn a process per turn, and you pay it per turn. The fix for stock codex, no fork required: ~/.codex/config.toml otel metrics exporter = "none" Prompt comes back as soon as the answer does. The multi-turn win is not a Bun result. I ran the same client through the built package under Node 22: identical numbers. The architecture — one long-lived process speaking JSON-RPC instead of a spawn per turn — delivers the win on either runtime. Bun's own wins are in the toolchain: test startup 1.2 s → 22 ms, warm install 1.4 s → 13 ms, the JSON-lines parser ~2x faster on unchanged code. And one number went the wrong way before it went right: generated protocol types blew the published package from 61 KB to 475 KB. Rolling the declarations into a single tree-shaken index.d.ts brought it to 75 KB — without hand-writing a single type. There's a CI gate now so it can't creep back. The complete article has the sequence diagrams, the p99 tables, the lifecycle story what happens when the persistent process crashes mid-turn , the second exit-tax I found after telemetry MCP session teardown , and the parts where my first conclusions were wrong: → Read the full article on Substack https://praveenvijayan.substack.com/p/i-rebuilt-the-codex-cli-harness-on Code, benchmarks, and the runnable side-by-side demo: github.com/praveenvijayan/codex, branch bundex-bench — bench/demo-turns.mjs reproduces the table above in two commands