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:

  1. Checks for an existing broker via session state in broker.json
  2. Spawns app-server-broker.mjs if no broker is running
  3. Writes the PID and socket path to broker.json for persistence
  4. 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_CODE or 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 broker as a transport option alongside http, 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.mjs generates cross-platform IPC endpoint strings (Unix sockets or Windows pipes)
  • broker-lifecycle.mjs manages broker process creation, discovery, and persistence via broker.json
  • app-server.mjs implements BrokerCodexAppServerClient for JSON-RPC over the broker with automatic fallback
  • app-server-broker.mjs runs 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:

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 →