Files
paseo/CODEX_SDK_BINARY_INVESTIGATION.md
T

8.4 KiB
Raw Blame History

Codex SDK Binary Investigation Report

Date: 2025-12-20 SDK Version: @openai/codex-sdk@0.76.0 Status: ✅ System binary usage is fully supported


Executive Summary

The @openai/codex-sdk library DOES support using a system-installed Codex binary instead of the embedded one. This is accomplished via the codexPathOverride configuration option in the CodexOptions interface.


How the SDK Currently Locates the Codex Binary

Default Behavior (Embedded Binary)

When no override is provided, the SDK uses the findCodexPath() function to locate the embedded binary:

Source: dist/index.js:278-330

function findCodexPath() {
  const { platform, arch } = process;
  let targetTriple = null;

  // Determines platform-specific binary path
  // e.g., "aarch64-apple-darwin" for Apple Silicon Macs

  const vendorRoot = path2.join(scriptDirName, "..", "vendor");
  const archRoot = path2.join(vendorRoot, targetTriple);
  const codexBinaryName = process.platform === "win32" ? "codex.exe" : "codex";
  const binaryPath = path2.join(archRoot, "codex", codexBinaryName);
  return binaryPath;
}

Binary Location Structure

The SDK ships with pre-compiled binaries in the vendor/ directory:

node_modules/@openai/codex-sdk/
├── vendor/
│   ├── aarch64-apple-darwin/codex/codex       (40MB - Apple Silicon)
│   ├── x86_64-apple-darwin/codex/codex        (Intel Mac)
│   ├── aarch64-unknown-linux-musl/codex/codex (ARM Linux)
│   ├── x86_64-unknown-linux-musl/codex/codex  (x86_64 Linux)
│   ├── aarch64-pc-windows-msvc/codex/codex.exe (ARM Windows)
│   └── x86_64-pc-windows-msvc/codex/codex.exe (x86_64 Windows)

Configuration Options Available

codexPathOverride Option

Type Definition: dist/index.d.ts:209-218

type CodexOptions = {
    codexPathOverride?: string;  // ← THIS IS THE KEY OPTION
    baseUrl?: string;
    apiKey?: string;
    env?: Record<string, string>;
};

Implementation: dist/index.js:336-338

constructor(options = {}) {
  this.exec = new CodexExec(options.codexPathOverride, options.env);
  this.options = options;
}

How it works: dist/index.js:145-147

constructor(executablePath = null, env) {
  this.executablePath = executablePath || findCodexPath();
  this.envOverride = env;
}

The codexPathOverride is passed as executablePath. If provided, it bypasses the findCodexPath() function entirely.


How to Use a System Codex Binary

Method 1: Direct Path Specification

import { Codex } from '@openai/codex-sdk';

const codex = new Codex({
  codexPathOverride: '/Users/moboudra/.asdf/installs/nodejs/22.20.0/bin/codex'
});

Method 2: Dynamic PATH Resolution

import { Codex } from '@openai/codex-sdk';
import { execSync } from 'child_process';

const systemCodexPath = execSync('which codex', { encoding: 'utf8' }).trim();

const codex = new Codex({
  codexPathOverride: systemCodexPath
});

Method 3: Environment Variable Based (Custom Implementation)

import { Codex } from '@openai/codex-sdk';

const codex = new Codex({
  codexPathOverride: process.env.CODEX_BINARY_PATH || undefined
});

Note: The SDK does NOT have a built-in environment variable for this purpose. The CODEX_BINARY_PATH above is a custom convention you'd need to implement in your application.


Verification Test Results

Test Configuration

  • System Codex: /Users/moboudra/.asdf/installs/nodejs/22.20.0/bin/codex
  • Embedded Codex: node_modules/@openai/codex-sdk/vendor/aarch64-apple-darwin/codex/codex
  • Versions: Both are codex-cli 0.76.0

Test Results

$ node test-codex-path-override.mjs
Testing codexPathOverride option...

Test 1: Using default embedded binary
✓ Created Codex instance with default settings

Test 2: Using system binary via codexPathOverride
✓ Created Codex instance with codexPathOverride

Test 3: Using which codex result
System codex location: /Users/moboudra/.asdf/installs/nodejs/22.20.0/bin/codex
✓ Created Codex instance with system codex from PATH

✅ All tests passed!

Benefits of Using System Codex

1. Version Control

  • Update codex independently via package manager (npm, brew, asdf, etc.)
  • No need to wait for SDK release to get latest codex features
  • Easier to test beta/development versions

2. Disk Space Savings

  • Embedded binary: ~40MB per architecture
  • In a monorepo with multiple node_modules: Saves 40MB × number of installations
  • System binary: Single installation regardless of projects

3. Consistency

  • Same codex version across all tools and SDKs
  • Easier debugging when CLI and SDK use identical binaries
  • Simplified version management

4. Development Workflow

  • Test local codex builds without reinstalling SDK
  • Point to custom-compiled binaries for debugging
  • A/B test different codex versions easily

Potential Considerations

1. Version Compatibility

  • SDK expects specific codex CLI behavior
  • Using mismatched versions might cause issues
  • SDK is at v0.76.0, ensure system codex matches or is compatible

2. PATH Availability

  • System binary must be accessible when Node.js process runs
  • Consider environment differences (development vs production)
  • Absolute paths are safer than relying on PATH resolution

3. No Fallback

  • If codexPathOverride points to invalid/missing binary, execution will fail
  • SDK doesn't automatically fall back to embedded binary
  • Implement error handling if using dynamic resolution

Environment Variables (Built-in)

The SDK does NOT provide a built-in environment variable for binary path override, but it does use these:

Used by SDK

  1. CODEX_INTERNAL_ORIGINATOR_OVERRIDE (Internal)

    • Source: dist/index.js:140-141
    • Set to "codex_sdk_ts" to identify SDK usage
    • Not for user configuration
  2. OPENAI_BASE_URL (Configurable)

    • Override via CodexOptions.baseUrl
    • Also injectable via env
  3. CODEX_API_KEY (Configurable)

    • Override via CodexOptions.apiKey
    • Also injectable via env

NOT Provided

  • ❌ CODEX_BINARY_PATH - Not a built-in feature
  • ❌ CODEX_PATH - Not a built-in feature
  • ❌ Auto-discovery via system PATH - Not implemented

For maximum flexibility, consider this pattern:

import { Codex } from '@openai/codex-sdk';
import { execSync } from 'child_process';
import { existsSync } from 'fs';

function createCodexInstance(options = {}) {
  // Priority order:
  // 1. Explicit override in options
  // 2. Environment variable
  // 3. System PATH
  // 4. Embedded binary (SDK default)

  let codexPath = options.codexPathOverride;

  if (!codexPath && process.env.CODEX_BINARY_PATH) {
    codexPath = process.env.CODEX_BINARY_PATH;
  }

  if (!codexPath) {
    try {
      codexPath = execSync('which codex', { encoding: 'utf8' }).trim();
      if (!existsSync(codexPath)) {
        codexPath = undefined;
      }
    } catch {
      // Fall back to embedded binary
      codexPath = undefined;
    }
  }

  return new Codex({
    ...options,
    codexPathOverride: codexPath
  });
}

// Usage
const codex = createCodexInstance();

Summary

Question Answer
Can SDK use system codex? ✅ Yes, via codexPathOverride
Is configuration option available? ✅ Yes, in CodexOptions interface
Built-in env variable support? ❌ No, must implement custom logic
Automatic PATH resolution? ❌ No, must provide explicit path
Fallback to embedded? ❌ No, fails if override is invalid
Version tested 0.76.0 (both system and embedded)

Conclusion

The @openai/codex-sdk library provides full support for using a system-installed Codex binary through the codexPathOverride configuration option. This feature is well-designed and allows developers to choose between the convenience of embedded binaries and the flexibility of system-managed installations.

To use a system binary:

  1. Install codex globally (via npm, brew, asdf, etc.)
  2. Pass the path via codexPathOverride when instantiating Codex
  3. Optionally implement PATH resolution logic for automatic discovery

The embedded binary remains the default, ensuring the SDK works out-of-the-box without requiring system-wide codex installation.