# How the Codex Plugin Handles Job Status Polling: CLI Architecture and Implementation

> Discover how the Codex plugin handles job status polling. Explore the CLI architecture and implementation details within codex-companion.mjs for efficient status checks.

- Repository: [OpenAI/codex-plugin-cc](https://github.com/openai/codex-plugin-cc)
- Tags: internals
- Published: 2026-07-08

---

**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

```bash

# 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)

```javascript
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; parses `status` sub-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 as `getCodexAvailability` and 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 `status` sub-command with the `--wait` flag.
- **Polling defaults** are 2-second intervals with a 240-second timeout, configurable via CLI flags.
- **Active detection** relies on `isActiveJobStatus` checking for `"queued"` or `"running"` states.
- **Core loop logic** lives in `waitForSingleJobSnapshot` inside `codex-companion.mjs`.
- **Data enrichment** occurs through `job-control.mjs` utilities 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.