# What Is the App Server Broker and How Does It Communicate with Codex?

> Discover the app server broker, a JSON-RPC proxy connecting Claude Code to the Codex CLI. Learn how it enables concurrent processes to share a single Codex instance using Unix domain sockets.

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

---

**The app server broker is a lightweight JSON-RPC proxy that sits between Claude Code and the Codex CLI app-server, enabling multiple concurrent processes to share a single Codex instance via Unix domain sockets and serialized request forwarding.**

The `openai/codex-plugin-cc` repository implements the app server broker to solve the limitation where only one client can directly control the Codex app-server at a time. By exposing a stable socket endpoint and managing request queuing, the broker allows Claude Code to multiplex operations while maintaining strict isolation between streaming sessions.

## Architecture of the App Server Broker

The broker acts as a centralized traffic controller. It accepts JSON-RPC messages from multiple client sockets, forwards them to a single Codex app-server process, and routes responses and notifications back to the appropriate clients.

### Broker Startup and Socket Initialization

The broker is started via the command line defined in `plugins/codex/scripts/app-server-broker.mjs` (lines 48‑66):

```bash
node plugins/codex/scripts/app-server-broker.mjs serve --endpoint <socket-path> [--cwd <dir>] [--pid-file <file>]

```

Upon initialization, the broker creates a Unix domain socket (or named pipe) at the supplied `--endpoint` and optionally persists its process ID to a file for lifecycle management. This socket becomes the stable entry point for all Claude Code components.

### Client Connection Handling

The broker uses Node.js `net.createServer` (lines 18‑34 and 46 in `app-server-broker.mjs`) to listen for incoming connections. Each client socket communicates via newline‑delimited JSON, sending JSON‑RPC requests one per line. The broker maintains internal state to track which socket currently owns the active request or stream.

### Connecting to the Codex App Server

When the first request arrives, the broker initializes a `CodexAppServerClient` via the static `connect` method implemented in `plugins/codex/scripts/lib/app-server.mjs` (lines 35‑53). This method determines whether to spawn a fresh Codex process (`SpawnedCodexAppServerClient`) or connect to an existing broker instance (`BrokerCodexAppServerClient`). The environment variable `CODEX_COMPANION_APP_SERVER_ENDPOINT` stores the socket path used for this connection.

## Request Management and Communication Flow

Once established, the app server broker governs all traffic between Claude Code and Codex through a strict ownership model that prevents request collisions.

### Serialized Request Forwarding

For each JSON‑RPC request, the broker checks whether the Codex app-server is busy (lines 70‑84 and 174‑182 in `app-server-broker.mjs`):

- **If free:** The request is forwarded to Codex, and the client socket becomes the *active request socket*.
- **If busy:** The broker returns error code `BROKER_BUSY_RPC_CODE` (`‑32001`), signaling that the client must retry.

This serialization ensures that stateful operations do not interleave.

### Streaming Method Handling

Certain Codex methods—specifically `turn/start`, `review/start`, and `thread/compact/start`—initiate long‑running streams. When these are invoked, the broker marks the client socket as the *active stream socket* (lines 174‑182). This socket remains attached to receive subsequent server‑sent notifications until the stream completes, blocking other clients from initiating new streams but allowing them to queue interrupt requests.

### Interrupt Handling

The broker supports out‑of‑band cancellation via the `turn/interrupt` method. Even while a streaming request occupies the active stream socket, the broker routes interrupt requests to the Codex app-server (lines 70‑73), enabling users to cancel long‑running operations without waiting for stream completion. This is guarded by the `allowInterruptDuringActiveStream` check at line 71.

### Notification Routing

The Codex client registers a notification handler using `setNotificationHandler(routeNotification)` (line 85). When the app-server emits notifications—such as `turn/completed`—the `routeNotification` function (lines 84‑100) delivers them to either the socket that initiated the request or the currently active stream socket, ensuring asynchronous events reach the correct recipient.

### Graceful Shutdown

Clients can trigger a clean shutdown by sending the `broker/shutdown` RPC. The broker responds, then closes all client sockets, stops the internal Codex client, unlinks the Unix socket file, and deletes the PID file (lines 60‑66 and the `shutdown` function at line 102).

## Implementation Details and Key Files

The app server broker architecture spans several modules in the `openai/codex-plugin-cc` repository:

| File | Purpose |
|------|---------|
| `plugins/codex/scripts/app-server-broker.mjs` | Main broker process; implements socket server, request serialization, and stream management. |
| `plugins/codex/scripts/lib/app-server.mjs` | Defines `CodexAppServerClient` with dual connection strategies (direct spawn vs. broker proxy). |
| `plugins/codex/scripts/lib/broker-endpoint.mjs` | Parses `--endpoint` arguments into structured socket configurations. |
| `plugins/codex/scripts/lib/broker-lifecycle.mjs` | Manages PID files and session persistence across plugin invocations. |
| `plugins/codex/scripts/codex-companion.mjs` | High‑level entry point that consumes the broker to serve Claude Code commands. |

## Practical Usage Examples

Launch the broker programmatically (normally handled automatically by the plugin):

```javascript
import { spawn } from "node:child_process";

spawn("node", [
  "plugins/codex/scripts/app-server-broker.mjs",
  "serve",
  "--endpoint", "/tmp/codex-broker.sock",
  "--pid-file", "/tmp/codex-broker.pid"
]);

```

Acquire a client via the broker endpoint to send requests:

```javascript
import { CodexAppServerClient } from "./plugins/codex/scripts/lib/app-server.mjs";

async function runReview() {
  // Connects via CODEX_COMPANION_APP_SERVER_ENDPOINT if set
  const client = await CodexAppServerClient.connect(process.cwd());
  const result = await client.request("review/start", { /* …params… */ });
  console.log("Review result:", result);
  await client.close();
}
runReview();

```

## Summary

- The **app server broker** is a JSON‑RPC proxy in `openai/codex-plugin-cc` that multiplexes access to the Codex CLI app-server.
- It exposes a **Unix domain socket** for multiple Claude Code processes to connect concurrently.
- Requests are **serialized**; if the server is busy, the broker returns error code `‑32001`.
- **Streaming methods** (`turn/start`, `review/start`, `thread/compact/start`) lock the active stream socket until completion.
- **Interrupt requests** (`turn/interrupt`) can bypass the lock to cancel operations.
- All communication occurs over **newline‑delimited JSON** via `net.createServer` sockets.

## Frequently Asked Questions

### What is the app server broker in the Codex plugin?

The app server broker is a Node.js process defined in `plugins/codex/scripts/app-server-broker.mjs` that acts as a JSON-RPC reverse proxy. It allows multiple Claude Code instances to communicate with a single Codex app-server by serializing requests and managing socket ownership, preventing concurrent state corruption.

### How does the broker handle concurrent requests from multiple Claude Code processes?

The broker accepts connections from multiple clients but only forwards one request at a time to the Codex app-server. If a second client sends a request while the server is busy, the broker immediately responds with `BROKER_BUSY_RPC_CODE` (`‑32001`), forcing the client to retry. Streaming requests lock the connection until the stream ends, while non‑streaming requests are processed sequentially.

### What happens when I try to interrupt a running Codex operation?

The broker allows `turn/interrupt` requests to pass through even when an active stream (from `turn/start`, `review/start`, or `thread/compact/start`) is holding the active socket. This is implemented via the `allowInterruptDuringActiveStream` check in `app-server-broker.mjs` (lines 70‑73), enabling cancellation of long‑running operations without waiting for natural completion.

### How do I shut down the app server broker gracefully?

Send a `broker/shutdown` JSON‑RPC request to the broker's socket. The broker will acknowledge the request, close all client connections, terminate the underlying Codex app-server process, remove the Unix socket file, and delete its PID file. This functionality is implemented in the `shutdown` function at line 102 of `app-server-broker.mjs`.