How to Execute Long-Running Codex Tasks in the Background with openai/codex-plugin-cc

Use the --background flag in codex-companion.mjs to detach long-running Codex jobs into isolated Node processes, then monitor progress with /codex:status and retrieve results via /codex:result.

The openai/codex-plugin-cc repository provides a robust background execution system that prevents the Claude Code UI from freezing during lengthy reviews, adversarial analyses, or rescue tasks. By leveraging process isolation and atomic state persistence, you can execute long-running Codex tasks in the background while maintaining full visibility into job progress and final outputs.

Why Background Execution Matters for Codex Workloads

Codex reviews and rescue tasks can take minutes when processing large codebases or using high-effort reasoning models. Running these operations in the foreground blocks your terminal and prevents concurrent work. The plugin solves this by implementing a detached worker architecture that spawns independent Node processes, stores progress in JSON files under .codex/jobs/, and provides CLI commands to query or cancel jobs asynchronously.

How the Background Execution System Works

Command Parsing and Job Creation

When you append --background to any command, the parseCommandInput function in codex-companion.mjs (lines 41-48) sets options.background = true. This triggers handleTask to call enqueueBackgroundTask (lines 84-100) rather than executing synchronously.

The system creates a structured job object via buildTaskJob (lines 62-71), which assigns a unique jobId, defines the log file path, and writes an initial queued record to disk using createTrackedProgress.

The Detached Worker Architecture

The enqueueBackgroundTask function spawns a detached child process through spawnDetachedTaskWorker (lines 71-80). This worker runs independently of the parent Claude Code process, ensuring that crashes or memory-intensive operations do not affect your active session.

The detached child executes handleTaskWorker, which reads the stored request and runs runTrackedJob from tracked-jobs.mjs. This function updates the job file in-place, transitioning the status from "queued" to "running" and finally to "completed" or "failed".

Progress Tracking and State Persistence

Progress events flow through createJobProgressUpdater in tracked-jobs.mjs (lines 70-95), which writes JSON-structured log lines to the job-specific *.log file. The system uses atomic updates via writeJobFile in state.mjs to prevent corruption during concurrent writes.

Jobs are automatically scoped to your current Claude session using SESSION_ID_ENV, ensuring that multiple users on the same repository do not see each other's background tasks unless they share a session ID.

Best Practices for Background Codex Tasks

Always Use --background for Long-Running Operations

For reviews, adversarial reviews, and rescue tasks that exceed a few seconds, append the --background flag to prevent UI freezing:

node scripts/codex-companion.mjs review --background --base main

This returns a JSON payload containing the jobId, status: "queued", and logFile path, allowing immediate terminal access.

Monitor the Structured Log File

Each background job writes detailed progress to a log file adjacent to its JSON state file in .codex/jobs/. Use cat or tail commands on the logFile path returned during job creation to inspect real-time progress outside of the CLI interface.

Set Appropriate Reasoning Effort Levels

High-effort reasoning (--effort high) dramatically increases latency. For background jobs where completion time is flexible, specify your time budget explicitly:

node scripts/codex-companion.mjs task --background --effort medium "refactor authentication logic"

Prefer Explicit Model Aliases

Avoid ambiguity by specifying model aliases directly. The MODEL_ALIASES map in codex-companion.mjs translates shortcuts like spark to gpt-5.3-codex-spark:

node scripts/codex-companion.mjs rescue --background --model spark "investigate flaky tests"

Cancel Runaway Jobs Immediately

If a background job consumes excessive tokens or enters an infinite loop, terminate it using the saved PID:

node scripts/codex-companion.mjs cancel task-2026-07-05-13-42-01

The plugin calls terminateProcessTree and updates the job status to "cancelled" atomically.

Resume Previous Tasks to Save Context

Use --resume-last to pick the most recent successful task thread, reusing context and reducing token usage:

node scripts/codex-companion.mjs task --background --resume-last "continue the refactor"

Poll Job Status Programmatically

Query the current state without blocking using /codex:status:

node scripts/codex-companion.mjs status task-2026-07-05-13-42-01

This reads the stored JSON via readStoredJob in job-control.mjs and returns the current phase, timestamps, and completion percentage.

Persist Job IDs for Automation

Store the jobId in environment variables when scripting CI pipelines:

export CODX_JOB=$(node scripts/codex-companion.mjs task --background "analyze dependencies" | jq -r .jobId)

# Later retrieval:

node scripts/codex-companion.mjs result $CODX_JOB

Verify CLI Installation Before Queuing

Background jobs require the Codex CLI binary to be installed and authenticated. Run /codex:setup before enqueueing tasks to avoid immediate failures in the detached worker.

Avoid Conflicting Flags

The --background and --wait flags are mutually exclusive. The code in parseCommandInput will throw if both are specified, so choose one execution mode per command.

Practical Examples

Queueing a Code Review in the Background

Start a comprehensive review on your main branch without blocking your terminal:

node scripts/codex-companion.mjs review --background --base main --effort high

Expected output:

{
  "jobId": "task-2026-07-05-13-42-01",
  "status": "queued",
  "title": "Codex Review",
  "summary": "Running review on branch main",
  "logFile": "/path/to/.codex/jobs/task-2026-07-05-13-42-01.log"
}

Monitoring Progress and Retrieving Results

Check the current status while the job runs:

node scripts/codex-companion.mjs status task-2026-07-05-13-42-01

Once completed, fetch the final rendered output:

node scripts/codex-companion.mjs result task-2026-07-05-13-42-01

The render.mjs module (lines 60-66) handles formatting the result or displaying error payloads if the job failed.

Canceling a Background Task

If you need to abort a job:

node scripts/codex-companion.mjs cancel task-2026-07-05-13-42-01

This looks up the PID in the job record, terminates the process tree, and updates the status to "cancelled" via upsertJob in state.mjs.

Summary

  • Use --background to detach long-running Codex operations from the Claude Code UI, preventing terminal freezes.
  • Monitor jobs via /codex:status and retrieve outputs with /codex:result, both of which read from JSON files in .codex/jobs/.
  • Cancel efficiently using /codex:cancel, which terminates the specific PID stored in the job record.
  • Optimize resources by setting --effort levels appropriately and using --resume-last to reuse context from previous tasks.
  • Ensure isolation through the detached worker architecture in spawnDetachedTaskWorker, which protects your main session from crashes or memory spikes.

Frequently Asked Questions

What happens if I close Claude Code while a background job is running?

The detached worker process continues executing independently because spawnDetachedTaskWorker creates a separate Node process with its own PID. When you reopen Claude Code, use /codex:status or /codex:result with the job ID to retrieve the current state or final output from the persisted JSON files in .codex/jobs/.

How do I know when my background Codex task is complete?

Poll the job status using node scripts/codex-companion.mjs status <jobId>, which reads the atomic state updates written by writeJobFile. The status field transitions from "queued" to "running" and finally to "completed" or "failed", with timestamps recorded for each phase change.

Can I run multiple background Codex jobs simultaneously?

Yes. Each call to enqueueBackgroundTask creates a unique job ID and spawns a separate detached process. Jobs are scoped to your current SESSION_ID_ENV, so you can queue multiple reviews or rescue tasks concurrently without interference, provided your system has sufficient resources.

What is the difference between --background and --wait?

The --background flag detaches the job immediately and returns a JSON payload with the job ID, while --wait would block the terminal until completion. These flags are mutually exclusive in the source code, and attempting to use both will cause parseCommandInput to throw an error.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →