How the Codex Plugin Handles Job Status Polling: CLI Architecture and Implementation
The Codex plugin implements job status polling through a dedicated status sub-command that loops every 2 seconds until a terminal state is reached or a 4-minute timeout expires, using logic defined in codex-companion.mjs.
The openai/codex-plugin-cc repository provides a robust mechanism for monitoring asynchronous Codex jobs through intelligent polling. When you invoke the status command with the --wait flag, the plugin enters a controlled loop that checks job state, sleeps for configurable intervals, and returns enriched status data. This article examines the exact implementation of Codex plugin job status polling, including the specific functions, constants, and file paths that drive the behavior.
Status Sub-Command Entry Point
The polling process begins in plugins/codex/scripts/codex-companion.mjs within the handleStatus function (lines 88-99). This entry point parses CLI arguments to determine whether a specific job ID was supplied and whether the --wait flag is present, routing the execution to either a single-job poll or a bulk status snapshot.
Polling Implementation Details
Active State Detection
Before entering the polling loop, the plugin evaluates whether a job requires monitoring through the isActiveJobStatus utility. This function returns true only when the job status is either "queued" or "running" (lines 90-92), ensuring the loop terminates immediately for terminal states like "completed" or "failed".
The Polling Loop
The core waiting logic resides in waitForSingleJobSnapshot (lines 18-33). This async function repeatedly invokes buildSingleJobSnapshot while isActiveJobStatus returns true, implementing a sleep interval controlled by DEFAULT_STATUS_POLL_INTERVAL_MS (default 2000ms). The loop also respects DEFAULT_STATUS_WAIT_TIMEOUT_MS (default 240000ms), exiting with an error if the job fails to reach a terminal state within the allotted time.
Snapshot Generation
Each iteration queries the current state through buildSingleJobSnapshot (lines 42-46). This function reads the job record from the workspace's JSON persistence layer and enriches it with progress metadata—such as elapsed time and execution phase—via helper functions exported from plugins/codex/scripts/lib/job-control.mjs.
Rendering and Output
Once polling completes or a snapshot is requested, the plugin delegates formatting to renderJobStatusReport for single jobs or renderStatusReport for bulk queries (lines 97-100, 106-108). These functions in plugins/codex/scripts/lib/render.mjs support both JSON output (--json flag) and human-readable table formats.
Usage Examples
CLI Polling Commands
# Show a compact table of all active and recent jobs
codex status
# Show detailed JSON for a specific job (no polling)
codex status abc123 --json
# Poll a job until it finishes (default 4-minute timeout)
codex status abc123 --wait
# Custom timeout and poll interval (e.g., 30s timeout, 1s interval)
codex status abc123 --wait --timeout-ms 30000 --poll-interval-ms 1000
Programmatic Use (Node.js)
import { spawn } from "node:child_process";
function pollJob(jobId, cwd = process.cwd()) {
const args = ["scripts/codex-companion.mjs", "status", jobId, "--wait"];
const proc = spawn("node", args, { cwd, stdio: "inherit" });
return new Promise((resolve, reject) => {
proc.on("close", (code) => (code === 0 ? resolve() : reject(new Error("Polling failed"))));
});
}
Key Source Files
plugins/codex/scripts/codex-companion.mjs– Main CLI driver; parsesstatussub-command, implements polling (waitForSingleJobSnapshot) and delegates rendering.plugins/codex/scripts/lib/job-control.mjs– Provides job sorting, enrichment, progress preview, and utilities used by the status snapshot builders.plugins/codex/scripts/lib/codex.mjs– Supplies helpers such asgetCodexAvailabilityand session-runtime status used by the status report.plugins/codex/scripts/lib/state.mjs– Handles persistence of job records (reading/writing JSON files) that the status logic queries.plugins/codex/scripts/lib/render.mjs– Contains rendering functions (renderJobStatusReport,renderStatusReport) that format the final output.
Summary
- The Codex plugin polls job status via the
statussub-command with the--waitflag. - Polling defaults are 2-second intervals with a 240-second timeout, configurable via CLI flags.
- Active detection relies on
isActiveJobStatuschecking for"queued"or"running"states. - Core loop logic lives in
waitForSingleJobSnapshotinsidecodex-companion.mjs. - Data enrichment occurs through
job-control.mjsutilities that append progress metadata to raw job records. - Output formatting supports both JSON and human-readable tables via dedicated render functions.
Frequently Asked Questions
What is the default polling interval for Codex job status?
The default polling interval is 2 seconds (2000ms), defined by the DEFAULT_STATUS_POLL_INTERVAL_MS constant in codex-companion.mjs. You can override this with the --poll-interval-ms flag when running codex status --wait.
How does the Codex plugin determine if a job is still active?
The plugin uses the isActiveJobStatus function (lines 90-92) to check if the job status equals "queued" or "running". If either condition is true, the polling loop continues; otherwise, it returns the final snapshot immediately.
What happens if a job status poll times out?
If the job does not reach a terminal state before DEFAULT_STATUS_WAIT_TIMEOUT_MS (240 seconds) elapses, the polling loop exits and returns an error. You can extend this limit using the --timeout-ms flag.
Can I poll job status programmatically instead of using the CLI?
Yes. You can spawn the codex-companion.mjs script directly from Node.js using child_process.spawn, passing the status, job ID, and --wait arguments. This allows integration into larger automation workflows while maintaining the same polling logic and output formatting.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →