How Tasks Are Spawned as Detached Processes for Background Jobs in Codex

Codex spawns background jobs as detached processes by setting delivery: "detached" in the task request, which the broker persists as detached: true in the job JSON file, allowing the CLI to exit immediately while the app-server continues execution in an isolated process group.

When you need tasks spawned as detached processes for background jobs with Codex, the openai/codex-plugin-cc repository implements a specialized delivery mechanism that decouples the CLI lifecycle from the worker execution. The workflow spans command parsing, broker persistence, and process isolation to ensure background tasks survive terminal exits.

Command Parsing and the Delivery Flag

When a user invokes the task command with the --background flag, the CLI translates this argument into a delivery configuration. In plugins/codex/scripts/lib/codex.mjs (lines 1020–1038), the code examines the delivery option and assigns the value "detached" when background execution is requested.

// From plugins/codex/scripts/lib/codex.mjs
if (delivery === "detached") {
  // mark the thread as detached so the broker knows
  state.threadId = response.reviewThreadId;
}

Thread Creation via runAppServerTask

The runAppServerTask function initiates the background worker by calling startThread on the Codex app-server. The request payload explicitly includes delivery: "detached" (lines 1026–1030 in codex.mjs), instructing the system to create an independent thread that persists after the parent shell returns.

// Trigger a background task programmatically
await codex.runTask({ prompt, delivery: "detached" });

Broker Persistence in broker-lifecycle.mjs

Once the broker receives the request in plugins/codex/scripts/lib/broker-lifecycle.mjs, it marks the job record with detached: true (lines 64–66). The broker writes this flag to the job’s JSON file on disk, creating a persistent record that survives CLI termination and enables status tracking across sessions.

// Inside broker-lifecycle.mjs
await writeJobFile(jobPath, { ...job, detached: true });

Process Isolation and Lifecycle Management

Because the job is flagged as detached, the Codex CLI does not wait for the app-server turn to finish. The CLI returns immediately to the shell, while the app-server continues running the task in its own process group. The terminateProcessTree helper can later target this entire group for cleanup if the job needs to be forcefully stopped.

Monitoring Background Jobs with job-control.mjs

Background workers are exposed through status commands via the job-control utilities in plugins/codex/scripts/lib/job-control.mjs. The enrichJob function (lines 1550–1552) reads the detached flag from the job JSON and includes it in status snapshots. When running /codex:status or similar queries, the system identifies detached jobs with a background indicator.

// Status command prints detached jobs
const status = buildStatusSnapshot(cwd);
status.running.forEach(j => {
  if (j.detached) console.log(`🔹 ${j.id} (background)`);
});

Summary

  • The --background flag triggers delivery: "detached" in the task request parsed by codex.mjs
  • The broker stores detached: true in the job's JSON file at plugins/codex/scripts/lib/broker-lifecycle.mjs
  • The CLI exits immediately while the app-server continues execution in an isolated process group
  • Status queries via enrichJob in plugins/codex/scripts/lib/job-control.mjs expose detached workers for monitoring
  • The terminateProcessTree helper can kill the entire process group when cleanup is required

Frequently Asked Questions

How do I spawn a background task in Codex?

Pass the --background flag to the task command. This sets delivery: "detached" in the request handled by runAppServerTask, creating a detached thread that persists after the CLI exits.

Where does Codex store the detached status of a job?

The broker writes the detached: true flag to the job's JSON file on disk in plugins/codex/scripts/lib/broker-lifecycle.mjs. The enrichJob function in plugins/codex/scripts/lib/job-control.mjs reads this value when building status reports.

Can I terminate a detached Codex process after the CLI exits?

Yes. Detached jobs run in their own process group, and the terminateProcessTree helper can target the entire group for cleanup. The job remains tracked in the Codex job store until explicitly removed or completed.

How can I check if a background job is still running?

Query the job status using /codex:status or similar commands. The buildStatusSnapshot function checks the detached flag in the job JSON and displays running background jobs with a background indicator.

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 →