| name | codex-sdk |
| description | Use the @openai/codex-sdk TypeScript SDK for programmatic code auditing. Hard-won API knowledge — constructor options, thread options, run options, structured output, streaming, timeouts. Prevents the exec/spawn pitfalls that waste hours. |
| triggers | ["codex","codex sdk","codex api","codex headless","code audit","openai codex","run codex","codex programmatic","codex typescript"] |
Codex TypeScript SDK (@openai/codex-sdk)
Official SDK for programmatic Codex CLI control. Always use the SDK — never shell out to codex exec via spawn/execFile (Codex writes to TTY not stdout, output capture is broken).
Installation
npm install @openai/codex-sdk
Auth: Uses ~/.codex/auth.json (from codex login). SDK reads it automatically.
Core API
import { Codex } from '@openai/codex-sdk';
const codex = new Codex({
apiKey?: string,
baseUrl?: string,
config?: CodexConfigObject,
env?: Record<string, string>,
});
const thread = codex.startThread({
workingDirectory: '/path/to/project',
sandboxMode: 'read-only',
skipGitRepoCheck: true,
approvalPolicy: 'never',
model?: string,
modelReasoningEffort?: string,
networkAccessEnabled?: boolean,
additionalDirectories?: string[],
});
const turn = await thread.run(prompt, {
outputSchema?: unknown,
signal?: AbortSignal,
});
turn.finalResponse
turn.items
turn.usage
Critical Gotchas (HARD-WON)
1. NEVER use execFile/spawn to run Codex CLI
Codex writes interactive output to TTY, not stdout. execFile gets empty stdout. spawn with shell: true splits multi-line prompts into separate args. spawn without shell can't resolve PATH. The SDK handles all of this internally.
2. Timeouts — use AbortSignal, not Promise.race
const ac = new AbortController();
const timer = setTimeout(() => ac.abort(), timeoutMs);
try {
const turn = await thread.run(prompt, { signal: ac.signal });
} finally {
clearTimeout(timer);
}
3. Codex code scans take 5-10+ minutes
A security audit of a medium Next.js codebase (~50 files in src/) takes 5-10 minutes. Set timeouts to at least 10 minutes (600000ms) for code audit tasks. Simple prompts ("list files") complete in ~15s.
4. Token usage is substantial
A full codebase scan uses ~1.9M input tokens (with caching). Budget accordingly.
5. Global AGENTS.md affects all sessions
Codex reads ~/.codex/AGENTS.md for every session. If it contains interactive prompts or mode-selection questions, Codex will respond to those instead of your prompt. Keep global config minimal.
6. outputSchema goes on thread.run(), NOT the constructor
const turn = await thread.run(prompt, { outputSchema: mySchema });
const codex = new Codex({ outputSchema: mySchema });
7. OpenAI Strict Structured Output rules (when using outputSchema)
- Every object MUST have
additionalProperties: false
- ALL properties MUST be in the
required array — no optional properties
- Nested objects need the same treatment
Streaming (for progress monitoring)
const { events } = await thread.runStreamed(prompt, { signal });
for await (const event of events) {
switch (event.type) {
case 'thread.started':
case 'turn.started':
case 'item.completed':
console.log(event.item?.type, event.item?.command);
break;
case 'turn.completed':
console.log(event.usage);
break;
case 'turn.failed':
console.log(event.error);
break;
}
}
Thread Resumption
const threadId = thread.id;
const resumed = codex.resumeThread(threadId, threadOptions);
await resumed.run("Continue from where we left off");
Sessions persist to ~/.codex/sessions/.
ThreadItem Types
The turn.items array contains:
agent_message — text response
reasoning — chain of thought
command_execution — shell command with output and exit code
file_change — file modifications (in write modes)
mcp_tool_call — MCP server calls
web_search — web search queries
todo_list — task tracking
error — error messages
bughunt Integration
bughunt (shipped at tools/bughunt/ in this repo, formerly known as WCC) uses this SDK in src/agents/codex-runner.ts for code audit agents (CodeSecurity, CodeLogic, CodeA11y, CodePerformance, CodeQuality). Each agent gets a specialised prompt, runs in read-only sandbox, and returns advisory findings as JSON.
Model Selection
const thread = codex.startThread({
model: 'o3',
});
const codex = new Codex({
config: { model: 'o3' },
});