Skip to content

investigation: @openai/codex-sdk does not work from compiled bun binaries (no embed equivalent, native binary dependency) #995

@Wirasm

Description

@Wirasm

Summary

@openai/codex-sdk cannot be used from a bun build --compile archon binary. Workflows that route to Codex will fail when invoked from the released binary, though they still work in dev (bun link) mode.

This was identified during the investigation of #990 (the Claude SDK equivalent problem) but was explicitly scoped out of that fix. This issue tracks the investigation and resolution for Codex.

Priority: P1 — Codex is a first-class provider alongside Claude, and shipping binaries that advertise "archon supports Claude and Codex" when Codex silently fails is a trust-breaker. Not a v0.3.2 blocker because v0.3.2's critical fixes were Claude-path only, but should be addressed before Codex gets promoted in docs or default workflow configs.

Two distinct problems with Codex + bun build --compile

Unlike @anthropic-ai/claude-agent-sdk which ships a dedicated /embed entry point for exactly this case, @openai/codex-sdk has two separate issues:

Problem 1 — Runtime path resolution via createRequire

node_modules/.bun/node_modules/@openai/codex-sdk/dist/index.js does:

const moduleRequire = createRequire(import.meta.url);
const codexPackageJsonPath = moduleRequire.resolve(`@openai/codex/package.json`);
// ...
const platformPackageJsonPath = codexRequire.resolve(`@openai/codex-darwin-arm64/package.json`);

This runs createRequire(import.meta.url) at runtime inside the compiled binary. In a bun --compile build, import.meta.url for a bundled module is frozen at build time to the build host's absolute path (same bug that affected Claude). Two possible outcomes:

  • createRequire is called with a /$bunfs/ path → resolution fails because $bunfs doesn't participate in normal Node module resolution
  • createRequire is called with the build host's absolute path → resolution fails on the user's machine because that path doesn't exist

Either way, Codex can't locate its own package.json, and everything downstream breaks.

Problem 2 — Native platform binary dependency

Codex CLI is a Rust-compiled binary shipped via platform-specific optional dependencies:

  • @openai/codex-darwin-arm64 → ships vendor/aarch64-apple-darwin/codex/codex
  • @openai/codex-darwin-x64 → ships vendor/x86_64-apple-darwin/codex/codex
  • @openai/codex-linux-arm64 → ships vendor/aarch64-linux-gnu/codex/codex
  • @openai/codex-linux-x64 → ships vendor/x86_64-linux-gnu/codex/codex

bun build --compile cannot embed these via import ... with { type: 'file' } because they are native executables, not JavaScript. Even if we fixed Problem 1, the binary wouldn't be accessible from inside the compiled archon artifact because bun's bundler doesn't know how to handle arbitrary native files as bundled assets (as of Bun 1.3.x).

What currently "works" and what doesn't

Dev mode (bun link): Codex works fine. The SDK resolves @openai/codex/package.json via normal node_modules resolution, finds the platform-specific native binary in node_modules/@openai/codex-<platform>/vendor/.../codex, and spawns it as a subprocess. No issues.

Compiled binary (bun build --compile): Codex fails. The createRequire call either returns a /$bunfs/ path that can't be resolved or a build-host path that doesn't exist. Even if the path issue is worked around, the native Codex binary is not extractable from the archon binary.

Current user impact

Anyone using the released archon binary who has a workflow routed to Codex will hit a cryptic error when the first Codex-backed node executes. The error is not well-formatted because it bubbles up from createRequire internals, not from archon's error handling.

What users see today: a stack trace from deep inside @openai/codex-sdk with no indication that the problem is "you're running a binary build and Codex isn't supported in binary mode." This is worse than failing fast with a clear error.

Investigation tasks

Before proposing a fix, we need to answer:

1. Does @openai/codex-sdk have any published embed-for-bun pattern?

Check the SDK's README, release notes, and GitHub issues for any documented approach to compiled-binary support. Claude SDK ships /embed as a deliberate entry point — does OpenAI have an equivalent planned or shipped?

Specifically:

  • Read the full index.js to map every createRequire / import.meta.url usage
  • Check if there's a CODEX_BIN_PATH env var or constructor option analogous to pathToClaudeCodeExecutable
  • Search the GitHub repo for issues mentioning "bun compile", "standalone binary", "pkg", or "nexe"
  • Check if @openai/codex-sdk's versioning includes any bundler-friendly variants

2. Can we ship the native Codex binary as a separate release asset?

Possible approach: the archon release workflow builds the archon binary AND downloads the platform-specific Codex native binary, then ships both as release assets. The archon binary includes logic to locate the Codex binary in a known location (next to itself, or in ~/.archon/vendor/codex/).

Questions:

  • What's the size of the Codex native binary per platform? If it's small (< 20 MB), shipping alongside is fine. If it's huge (> 100 MB), this is unacceptable overhead.
  • License implications — are we allowed to redistribute the Codex native binary as a release asset under OpenAI's terms?
  • Can archon fetch it at install time via install.sh instead of shipping it directly?

3. Should compiled binaries fail fast on Codex-backed workflows?

Short-term mitigation: if we detect we're in a compiled binary (BUNDLED_IS_BINARY === true) and the workflow selects the Codex provider, throw an immediate error with clear remediation:

Error: Codex is not supported in the archon binary install.

The @openai/codex-sdk requires a native platform binary that cannot be
embedded in bun-compiled releases. To use Codex, install archon from
source via `bun link` instead of via Homebrew or install.sh.

Affected workflow: <workflow-name>
Affected node: <node-id>

This is a stopgap, not a fix — it makes the failure loud and actionable instead of silent and mysterious.

4. Is there a WASM-compiled version of Codex CLI?

OpenAI's Codex CLI is Rust, which can target WASM. If a WASM build exists or could be produced, it could theoretically be embedded in the archon binary the same way resvg.wasm is embedded in the Claude SDK. This is the cleanest long-term answer but depends entirely on OpenAI's release choices.

Possible resolution paths (ordered by cost)

Option A — Fail fast with a clear error (stopgap, ~2 hours)

Detect compiled binary mode + Codex provider selection, throw CodexNotSupportedInBinaryError with clear remediation. Ships as part of v0.3.3 or similar. Users understand the limitation immediately and know they need a source install for Codex.

Pros: tiny diff, unblocks the current confusion, non-destructive to Claude users
Cons: advertises a limitation rather than fixing it; Codex users are locked out of the binary install path

Option B — Ship the Codex native binary as a release asset (~1-2 days)

Release workflow fetches platform-specific Codex native binaries from @openai/codex-<platform> npm packages at build time and uploads them alongside the archon binary. Archon's runtime code (via a new detectCodexBinaryPath() helper) looks for the Codex binary in a known location adjacent to the archon binary or in ~/.archon/vendor/codex/.

Also solves Problem 1 because we're no longer relying on the SDK's internal createRequire — we pre-resolve the path ourselves.

Pros: Codex works from the binary install path, matches Claude behavior
Cons: release assets grow (~20-50 MB per platform for Codex binaries), license check required, more CI complexity

Option C — Install.sh fetches Codex separately at install time (~1 day)

Keep archon binary small. install.sh detects platform, downloads the matching Codex binary to ~/.archon/vendor/codex/, sets up CODEX_BIN_PATH env var or archon config to point at it. Homebrew formula does equivalent via postinstall script.

Pros: archon binary stays lean, optional Codex install
Cons: install.sh becomes more complex, Homebrew formula is harder, another moving part

Option D — Runtime fetch on first Codex invocation (~1 day)

Archon binary detects first Codex workflow run, checks ~/.archon/vendor/codex/ for the binary, downloads it from GitHub releases if missing (same source as the release assets from Option B), caches for subsequent runs.

Pros: install experience identical to Claude, fetch happens lazily only when needed
Cons: first-run latency, requires network at first Codex use, download+cache logic has to be robust against partial downloads and corruption

Option E — Upstream request to OpenAI (~unknown)

File an issue at openai/openai-codex-typescript (or wherever the SDK lives) asking them to:

  1. Ship an /embed entry point analogous to Claude's
  2. Provide a CODEX_BIN_PATH env var override
  3. Support running from a pre-extracted binary at a configurable path

Real fix but on OpenAI's timeline. Not something we can deliver ourselves.

Recommended short-term action

Ship Option A in v0.3.3: fail fast with a clear error when a Codex workflow is invoked from a compiled binary. Small diff, big UX improvement over the current mysterious failure.

Then investigate Options B/C/D in parallel and pick the one that best matches archon's distribution story. My instinct says Option D (lazy runtime fetch) because it keeps the archon binary size down, the install experience matches Claude, and it gracefully degrades if the user never runs a Codex workflow. But Option B is the simplest and most similar to Claude's current pattern.

Files likely affected (Option A stopgap)

File Change
packages/core/src/clients/codex.ts Add BUNDLED_IS_BINARY check at the top of sendQuery() (or constructor), throw clear error if true
packages/core/src/clients/codex.test.ts Test that compiled mode throws the expected error
packages/docs-web/src/content/docs/reference/providers.md (or similar) Document "Codex is not supported in binary installs — use source install"
packages/cli/src/commands/setup.ts If user selects Codex as default during archon setup in a compiled binary, warn them

Files likely affected (Option B/D longer-term)

File Change
packages/core/src/clients/codex.ts Replace SDK's createRequire-based path resolution with an explicit detectCodexBinaryPath() that checks (a) next to archon binary, (b) ~/.archon/vendor/codex/, (c) standard node_modules (dev mode)
packages/core/src/utils/codex-binary-fetcher.ts (new, Option D only) Lazy download logic with checksum verification, atomic extract, cached path
scripts/build-binaries.sh Optionally fetch Codex native binaries for release assets (Option B)
.github/workflows/release.yml Upload Codex native binaries alongside archon binaries (Option B)
scripts/install.sh Download Codex binary at install time (Option C)
homebrew/archon.rb Add postinstall hook or resource block for Codex (Option C)

Validation after fix

  • test-release brew (or curl) runs a Codex-provider workflow end-to-end from the installed binary and it succeeds
  • Dev mode (bun link) still works unchanged
  • The stopgap error message (Option A) is tested against a fresh install + Codex workflow
  • Documentation clearly describes Codex's install path requirements
  • The archon setup flow warns Codex users if they're on a binary install

Related

Acknowledgement

The existence of this bug was confirmed during the investigation of #990 (the Claude SDK version of the same problem). Both SDKs have the same class of issue; Anthropic shipped a fix (/embed), OpenAI has not. Until OpenAI ships an equivalent or we work around it, Codex cannot be advertised as working in the archon binary install path.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High priority - Address soon, next in queuearchitectureArchitectural changes and designarea: clientsAI assistant clientsbugSomething is broken

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions