# How the Broker Endpoint Works for Shared Codex Runtime in openai/codex-plugin-cc

> Discover how the broker endpoint facilitates shared Codex runtime by enabling multiple clients to connect to a single app-server instance via JSON-RPC. Learn more.

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

---

**The broker endpoint is a platform-specific address (Unix socket or Windows named pipe) that enables multiple client processes to share a single Codex app-server instance through JSON-RPC communication.**

In the `openai/codex-plugin-cc` repository, the broker endpoint serves as the critical communication bridge for **shared runtime mode**. When you run multiple Codex commands in the same workspace, this endpoint ensures they all route through one persistent app-server process rather than spawning duplicates. Understanding how this endpoint is generated, parsed, and managed is essential for anyone working with the Codex plugin architecture.

## How the Broker Endpoint Is Generated

The endpoint creation logic lives in `plugins/codex/scripts/lib/broker-endpoint.mjs`. The `createBrokerEndpoint(sessionDir, platform)` function produces a transport-specific address based on the operating system.

### Unix-like platforms

On macOS and Linux, the function returns a **Unix socket path** prefixed with `unix:`:

```javascript
// broker-endpoint.mjs, lines 10-16
export function createBrokerEndpoint(sessionDir, platform) {
  if (platform !== 'win32') {
    return `unix:${path.join(sessionDir, 'broker.sock')}`;
  }
  // Windows handling...
}

```

The resulting string looks like `unix:/tmp/cxc-12345/broker.sock`.

### Windows platforms

On Windows, the function sanitizes the session directory name and creates a **named pipe**:

```javascript
// broker-endpoint.mjs, lines 11-14
const sanitized = sessionDir.replace(/[\\/]/g, '-');
const name = `codex-${sanitized}`;
return `pipe:\\\\..\\pipe\\${name}-codex-app-server`;

```

The `pipe:` prefix signals the transport type to downstream parsing logic. This abstraction allows the same broker code to operate across platforms without modification.

The generated endpoint is stored in a temporary **session directory** created by `createBrokerSessionDir()` in `broker-lifecycle.mjs` (lines 15-18).

## Parsing and Validating the Endpoint

When the broker process starts, it must interpret the endpoint string to open the correct transport. The `parseBrokerEndpoint(endpoint)` function (lines 19-40) splits the string into a structured `{kind, path}` object:

- **Pipe transport**: Recognized by the `pipe:` prefix (lines 24-30)
- **Unix transport**: Recognized by the `unix:` prefix (lines 32-38)
- **Invalid transport**: Unknown prefixes trigger an explicit error (line 40)

The parsed object is then passed to Node.js `net.createConnection` or `net.createServer` to establish the actual socket or pipe connection (see `broker-lifecycle.mjs` lines 19-22).

This two-phase approach—generate as a string, then parse into structured data—keeps the CLI interface simple while preserving runtime type safety.

## Broker Lifecycle Integration

The endpoint orchestrates three critical lifecycle phases in `broker-lifecycle.mjs`:

### Session creation

`ensureBrokerSession()` (lines 31-34) coordinates endpoint generation with process spawning:

1. Calls the endpoint factory (defaulting to `createBrokerEndpoint`)
2. Writes a PID file for tracking
3. Spawns `app-server-broker.mjs` with the endpoint as a command-line argument

### Readiness verification

`waitForBrokerEndpoint()` (lines 24-40) implements an active polling loop that attempts connections until the socket responds. This guarantees the broker is listening before any client transmits JSON-RPC messages, preventing race conditions during startup.

### Graceful shutdown

`sendBrokerShutdown(endpoint)` (lines 43-56) opens a dedicated connection, sends the special `broker/shutdown` JSON-RPC method, and awaits confirmation. This ensures clean termination rather than orphaned processes.

## Broker Process Behavior

The actual broker implementation in `plugins/codex/scripts/app-server-broker.mjs` consumes the parsed endpoint to establish its server:

| Behavior | Endpoint Usage |
|----------|---------------|
| **Listen for connections** | `server.listen(listenTarget.path)` (line 46), where `listenTarget` comes from `parseBrokerEndpoint(endpoint)` (line 64) |
| **Route JSON-RPC requests** | Messages received on the socket are forwarded to `appClient.request`; only one active socket allowed—additional connections receive a busy error (lines 73-82) |
| **Handle shutdown** | `broker/shutdown` method triggers `shutdown(server)` which removes the Unix socket file if present (lines 108-110) |

The **mutual exclusion** guarantee is enforced at the socket level: the broker tracks a single active request socket and rejects concurrent attempts. This serializes access to the underlying Codex app-server without requiring complex locking primitives.

## Why the Broker Endpoint Matters for Shared Runtime

When developers run sequential Codex commands—`codex review` followed by `codex turn`—the **shared runtime** mode reuses the same broker process for efficiency. The endpoint architecture enables this through three properties:

- **Address stability**: The session-derived path remains constant for a given workspace, allowing second and third commands to locate the running broker
- **Cross-platform transport abstraction**: Identical JSON-RPC logic operates over Unix sockets or Windows named pipes
- **Explicit lifecycle boundaries**: Endpoint creation, polling, and shutdown form a complete state machine with clear failure modes

The test suite in `tests/broker-endpoint.test.mjs` validates platform-specific formatting and round-trip parsing (lines 6-22), preventing regressions in transport compatibility.

## Code Examples

### Creating an endpoint for a new shared session

```javascript
import { createBrokerEndpoint } from 
  'plugins/codex/scripts/lib/broker-endpoint.mjs';

const sessionDir = '/tmp/cxc-abcdef';
const endpoint = createBrokerEndpoint(sessionDir, process.platform);
// macOS/Linux: "unix:/tmp/cxc-abcdef/broker.sock"
// Windows: "pipe:\\\\..\\pipe\\codex-tmp-cxc-abcdef-codex-app-server"

```

### Parsing an endpoint inside the broker process

```javascript
import { parseBrokerEndpoint } from 
  'plugins/codex/scripts/lib/broker-endpoint.mjs';

const endpointArg = process.argv[3]; // "--endpoint", "unix:/tmp/cxc-abc/broker.sock"
const { kind, path } = parseBrokerEndpoint(endpointArg);

// kind: 'unix', path: '/tmp/cxc-abc/broker.sock'
// These values feed directly into net.createServer()

```

### Spawning the broker with full lifecycle management

```javascript
import {
  ensureBrokerSession,
  sendBrokerShutdown
} from 'plugins/codex/scripts/lib/broker-lifecycle.mjs';

// Start shared runtime
const session = await ensureBrokerSession(process.cwd());
console.log('Broker ready at:', session.endpoint);

// Later: clean termination
await sendBrokerShutdown(session.endpoint);

```

## Summary

- The **broker endpoint** is a platform-prefixed address (`unix:` or `pipe:`) stored in a temporary session directory
- `createBrokerEndpoint()` generates transport-specific strings while `parseBrokerEndpoint()` validates and structures them for Node.js networking APIs
- The **broker lifecycle** (creation → readiness polling → shutdown) coordinates process management around endpoint availability
- **Mutual exclusion** is enforced by socket ownership in `app-server-broker.mjs`, serializing access to the Codex app-server
- Platform abstraction allows identical JavaScript code to run on Linux, macOS, and Windows without transport-specific branching

## Frequently Asked Questions

### What happens if two Codex commands run simultaneously?

The broker endpoint enforces **single active connection** semantics. The first client socket receives full JSON-RPC service; subsequent connections receive an immediate error response indicating the broker is busy. Commands must serialize through the endpoint or retry.

### How does the broker handle stale endpoint files from crashed processes?

`ensureBrokerSession()` detects stale endpoints during session creation. If the endpoint exists but no process responds to connection attempts, the lifecycle manager tears down the orphaned resources and initializes a fresh broker with a clean endpoint.

### Can the broker endpoint be customized for custom deployments?

The `ensureBrokerSession()` function accepts an optional `createEndpoint` parameter, allowing injection of alternative endpoint factories. By default it uses `createBrokerEndpoint`, but deployments with specific socket path requirements can substitute custom logic while maintaining the same `kind:path` parsing contract.