How the Codex Plugin Communicates with the Codex App Server via the Broker RPC System
The Codex plugin communicates with the Codex app server through a lightweight broker process that exposes a JSON-RPC interface over local IPC (Unix domain sockets on POSIX, named pipes on Windows), enabling efficient, shared connections across multiple sub-agents.
This broker RPC system eliminates the overhead of repeatedly opening new network connections when multiple agents need to interact with the Codex app server. The implementation spans four core modules in openai/codex-plugin-cc that handle endpoint creation, lifecycle management, client-side communication, and the broker process itself.
Broker Endpoint Creation
The foundation of the communication layer is the endpoint string that identifies where the broker listens for connections.
In plugins/codex/scripts/lib/broker-endpoint.mjs, the createBrokerEndpoint(sessionDir, platform) function generates platform-specific IPC addresses:
- Windows: Returns a named pipe URI formatted as
pipe:\\\\.\\pipe\\<sanitized-name> - POSIX systems (Linux/macOS): Returns a Unix socket URI formatted as
unix:/path/to/broker.sock
The helper sanitizePipeName strips unsafe characters to ensure valid pipe names on Windows. This design guarantees cross-platform compatibility without code changes in higher layers.
Broker Lifecycle Management
Before any RPC calls occur, the plugin ensures a broker process exists for the current repository workspace.
In plugins/codex/scripts/lib/broker-lifecycle.mjs, the ensureBrokerSession(cwd, options) function:
- Checks for an existing broker via session state in
broker.json - Spawns
app-server-broker.mjsif no broker is running - Writes the PID and socket path to
broker.jsonfor persistence - Returns the endpoint to callers
The same module provides loadBrokerSession() and saveBrokerSession() for serializing and retrieving broker state across plugin invocations. This session file enables the broker to survive individual command executions while remaining discoverable by subsequent tool calls.
Client-Side JSON-RPC Communication
The plugin's client implementation bridges JavaScript method calls to JSON-RPC messages over the broker's IPC channel.
In plugins/codex/scripts/lib/app-server.mjs, the BrokerCodexAppServerClient class (extending AppServerClientBase) handles:
- Opening socket/pipe connections to the broker endpoint
- Framing requests as newline-delimited JSON-RPC objects:
{id, method, params} - Parsing responses and resolving returned promises
- Fallback logic: On
BROKER_BUSY_RPC_CODEor connection failures (ENOENT/ECONNREFUSED), automatically falls back to direct HTTP transport or retries
This client treats the broker as an alternative transport layer, maintaining the same API surface whether communicating directly with the app server or through the broker intermediary.
The Broker Process: Request Forwarding
The app-server-broker.mjs script runs as a persistent process that mediates all plugin-to-server communication.
Its responsibilities include:
- Listening on the endpoint created by
createBrokerEndpoint - Accepting JSON-RPC messages from multiple plugin clients
- Forwarding requests to the actual Codex app server (via HTTP or built-in client)
- Relaying responses back to the originating plugin
- Handling the special
"broker/shutdown"method for graceful termination
This architecture allows multiple sub-agents—such as review agents, rescue agents, or other Codex tooling—to share a single connection pool to the app server, reducing resource consumption and connection latency.
Working Example: Establishing Broker Communication
import { ensureBrokerSession } from "./lib/broker-lifecycle.mjs";
import { BrokerCodexAppServerClient } from "./lib/app-server.mjs";
async function getCodexClient(cwd) {
// 1️⃣ Ensure a broker is running for this repository
const broker = await ensureBrokerSession(cwd, { env: process.env });
const endpoint = broker.endpoint; // e.g. "unix:/tmp/repo/broker.sock"
// 2️⃣ Create a client that talks to the broker via JSON-RPC
const client = new BrokerCodexAppServerClient(cwd, {
brokerEndpoint: endpoint,
transport: "broker", // forces broker usage
});
return client;
}
// Example RPC call
(async () => {
const client = await getCodexClient(process.cwd());
const result = await client.call("codex/execute", { prompt: "Write a hello world script." });
console.log(result);
})();
Protocol Design and Performance Characteristics
The broker RPC system employs a simple, line-delimited JSON-RPC protocol that works uniformly across platforms. Key design decisions include:
- Newline-delimited streaming: Enables efficient message parsing without length-prefixing or complex framing
- Request multiplexing: A single broker connection supports concurrent requests from multiple agents
- Transport abstraction: The plugin treats
brokeras a transport option alongsidehttp, minimizing code divergence - Platform-native IPC: Uses the most performant local IPC mechanism available on each OS (domain sockets vs. named pipes)
Summary
broker-endpoint.mjsgenerates cross-platform IPC endpoint strings (Unix sockets or Windows pipes)broker-lifecycle.mjsmanages broker process creation, discovery, and persistence viabroker.jsonapp-server.mjsimplementsBrokerCodexAppServerClientfor JSON-RPC over the broker with automatic fallbackapp-server-broker.mjsruns as the intermediary process that forwards plugin requests to the Codex app server- The entire stack enables shared, reusable connections across multiple Codex sub-agents without repeated network overhead
Frequently Asked Questions
What IPC mechanisms does the broker RPC system use?
The broker RPC system uses Unix domain sockets on Linux and macOS, and Windows named pipes on Windows. The createBrokerEndpoint function in broker-endpoint.mjs automatically selects the appropriate mechanism based on the platform and sanitizes pipe names for Windows compatibility.
How does the plugin handle a broker that's already running?
The ensureBrokerSession function checks for an existing session file (broker.json) before spawning a new broker. If valid session state exists, it returns the existing endpoint rather than starting a duplicate process, enabling multiple plugin invocations to share the same broker instance.
What happens if the broker connection fails?
The BrokerCodexAppServerClient detects failures marked by BROKER_BUSY_RPC_CODE or connection errors (ENOENT, ECONNREFUSED). In these cases, it automatically falls back to direct HTTP transport to the Codex app server or retries the broker connection, ensuring resilience without manual intervention.
Can multiple agents use the same broker simultaneously?
Yes. The broker architecture specifically supports connection sharing across multiple sub-agents such as review agents, rescue agents, and other tooling. The broker acts as a multiplexing proxy, forwarding requests from any connected client to the Codex app server and returning responses to the correct originator.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →