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

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

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

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:

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.

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 →