# How the OpenAI Codex Plugin Manages Broker Session State: Persistence and Lifecycle Control

> Discover how the OpenAI Codex plugin manages broker session state by persisting it to a JSON file for efficient reuse and deterministic cleanup of resources.

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

---

**The Codex Companion plugin persists broker session state to a JSON file ([`broker.json`](https://github.com/openai/codex-plugin-cc/blob/main/broker.json)) in the repository's state directory, enabling lazy reuse of live broker processes across invocations while ensuring deterministic cleanup of stale or orphaned resources.**

The OpenAI Codex Companion plugin (`openai/codex-plugin-cc`) uses an optional broker process to mediate communication between the plugin and the Codex app-server. To avoid spawning duplicate processes and ensure reliable reconnection, the plugin implements a robust **broker session state** management system that tracks process metadata, Unix socket endpoints, and lifecycle status on disk.

## Where Broker Session State Is Stored

The plugin persists session data as JSON in the repository’s state directory, resolved via `resolveStateDir`. The helper `resolveBrokerStateFile(cwd)` constructs the full path to a file named **[`broker.json`](https://github.com/openai/codex-plugin-cc/blob/main/broker.json)** for a given working directory (lines 13‑14, 72‑74). This file acts as the single source of truth for broker metadata, allowing the plugin to reconnect to an existing broker or determine when a new one must be spawned.

## Anatomy of the Session Object

A broker session object contains five critical keys that are populated in `ensureBrokerSession`:

- **`endpoint`** – The Unix socket path the broker listens on, created by `createBrokerEndpoint`
- **`pidFile`** – Path to a file storing the broker’s process ID
- **`logFile`** – Path to the broker’s stdout/stderr log file
- **`sessionDir`** – Temporary directory holding the socket, PID file, and log
- **`pid`** – Process ID of the spawned broker process

The object is written to disk as pretty‑printed JSON via `saveBrokerSession` (lines 89‑93).

## The Session Lifecycle: From Creation to Teardown

The core routine `ensureBrokerSession(cwd, options)` orchestrates the entire lifecycle of the broker session state, handling reuse, cleanup, and spawning.

### Loading Existing Sessions

`loadBrokerSession(cwd)` attempts to read [`broker.json`](https://github.com/openai/codex-plugin-cc/blob/main/broker.json) from the state directory. If the file is missing or contains malformed JSON, the function returns `null` (lines 76‑86). This allows the client to decide whether to create a new broker or attempt reuse.

### Reusing or Cleaning Up Stale Sessions

Before reusing a session, the plugin validates its vitality:

1. If `loadBrokerSession` returns a valid object, `isBrokerEndpointReady` confirms the Unix socket is still alive (lines 13‑17).
2. If the session file exists but the endpoint is dead, the plugin calls `teardownBrokerSession` to clean up the socket, PID file, log, and temporary directory, followed by `clearBrokerSession` to remove the stale [`broker.json`](https://github.com/openai/codex-plugin-cc/blob/main/broker.json) (lines 19‑29).

This teardown eliminates orphaned resources from crashed or zombie broker processes.

### Spawning and Persisting New Brokers

When no valid session exists, the plugin executes a five-step creation flow:

1. **Directory creation** – `createBrokerSessionDir` establishes a new temporary directory.
2. **Endpoint generation** – `createBrokerEndpoint` generates the Unix socket path.
3. **Process launch** – `spawnBrokerProcess` launches `app-server-broker.mjs` in detached mode, redirecting stdout/stderr to the log file (lines 31‑48).
4. **Readiness polling** – `waitForBrokerEndpoint` polls the socket for up to 2 seconds. If the broker never becomes reachable, the plugin tears down the fresh process and returns `null` (lines 49‑60).
5. **Persistence** – On success, `saveBrokerSession` writes the session object to [`broker.json`](https://github.com/openai/codex-plugin-cc/blob/main/broker.json) and returns it to the caller (lines 62‑70).

## Cleanup and Resource Management

`teardownBrokerSession` performs safe, deterministic cleanup of broker resources:

- Optionally terminates the broker process via a custom `killProcess` function (e.g., `process.kill(pid, "SIGTERM")`)
- Removes the PID file, log file, and Unix socket if present
- Deletes the temporary session directory, ignoring errors for non‑empty or missing directories

All filesystem operations are wrapped in `try / catch` blocks to tolerate race conditions or missing resources (lines 73‑99).

## Integration Points in the Plugin Architecture

### Client-Side Broker Resolution

In `app-server.mjs`, when a client requests a broker transport, the plugin first attempts to `loadBrokerSession` if `options.reuseExistingBroker` is enabled. If no valid session exists, it falls back to `ensureBrokerSession` to create a new one (lines 339‑345).

### Shutdown Lifecycle Hooks

The `session-lifecycle-hook.mjs` module ensures graceful cleanup during plugin shutdown. It invokes `teardownBrokerSession` to terminate any broker that was started during the current session, preventing resource leaks when the editor or IDE closes (lines 85‑106).

### Test Coverage

The test suite in `runtime.test.mjs` and `broker-endpoint.test.mjs` verifies loading, saving, reusing, and cleaning up broker sessions, confirming the intended behavior across edge cases.

## Implementation Example

```javascript
import { ensureBrokerSession, loadBrokerSession, teardownBrokerSession } from "./lib/broker-lifecycle.mjs";

/* 1️⃣ Reuse an existing broker if it is alive */
const cwd = process.cwd();
let broker = loadBrokerSession(cwd);
if (broker && (await waitForBrokerEndpoint(broker.endpoint))) {
  console.log("Reusing broker at", broker.endpoint);
} else {
  /* 2️⃣ Otherwise, start a fresh broker */
  broker = await ensureBrokerSession(cwd, { env: process.env });
  console.log("Started new broker:", broker?.endpoint);
}

/* … use broker.endpoint to connect the Codex client … */

/* 3️⃣ Clean up when done */
if (broker) {
  await teardownBrokerSession({
    endpoint: broker.endpoint,
    pidFile: broker.pidFile,
    logFile: broker.logFile,
    sessionDir: broker.sessionDir,
    pid: broker.pid,
    killProcess: (pid) => process.kill(pid, "SIGTERM")
  });
}

```

## Key Files in the Broker State System

- **`plugins/codex/scripts/lib/broker-lifecycle.mjs`** – Core implementation of session persistence, creation, and teardown
- **`plugins/codex/scripts/lib/broker-endpoint.mjs`** – Helpers for constructing and parsing the Unix socket endpoint
- **`plugins/codex/scripts/app-server-broker.mjs`** – The actual broker process that serves RPC calls
- **`plugins/codex/scripts/lib/app-server.mjs`** – Client side that decides whether to reuse or create a broker
- **`plugins/codex/scripts/session-lifecycle-hook.mjs`** – Hook that invokes teardown on plugin shutdown
- **`tests/runtime.test.mjs`** – Test suite covering broker session lifecycle scenarios

## Summary

- **Broker session state** is persisted to [`broker.json`](https://github.com/openai/codex-plugin-cc/blob/main/broker.json) in the repository's state directory, tracking the Unix socket endpoint, PID, and temporary resource paths.
- The plugin lazily reuses existing brokers by validating socket vitality via `isBrokerEndpointReady`, avoiding unnecessary process creation.
- Stale sessions are automatically cleaned up through `teardownBrokerSession`, which removes orphaned sockets, log files, and temporary directories.
- New brokers are spawned with a 2‑second readiness timeout, ensuring the client never waits indefinitely for a failed startup.
- Shutdown hooks in `session-lifecycle-hook.mjs` guarantee deterministic cleanup of all broker resources when the plugin exits.

## Frequently Asked Questions

### Where is the broker session state stored?

The state is stored in a JSON file named [`broker.json`](https://github.com/openai/codex-plugin-cc/blob/main/broker.json) located within the repository’s state directory (resolved via `resolveStateDir`). The function `resolveBrokerStateFile(cwd)` constructs the absolute path based on the current working directory.

### How does the plugin detect if a broker is still alive?

The plugin uses `isBrokerEndpointReady` to check if the Unix socket path recorded in the session file is still responsive. This validation occurs before reusing a session in `ensureBrokerSession` (lines 13‑17), ensuring only active brokers are reclaimed.

### What happens if the broker process crashes while the session file exists?

If `loadBrokerSession` finds a session file but `isBrokerEndpointReady` determines the socket is dead, the plugin executes `teardownBrokerSession` to remove the stale socket, PID file, and log, followed by `clearBrokerSession` to delete the invalid [`broker.json`](https://github.com/openai/codex-plugin-cc/blob/main/broker.json). A fresh broker is then spawned automatically.

### How long does the plugin wait for a new broker to become ready?

The `waitForBrokerEndpoint` function polls the Unix socket for up to **2 seconds**. If the broker fails to become reachable within this window, the plugin tears down the partially started process and returns `null`, preventing the client from hanging indefinitely.