Understanding the broker-lifecycle Module in OpenAI Codex Plugin CC
The broker-lifecycle module is a persistence layer in openai/codex-plugin-cc that creates, loads, and saves broker sessions across plugin commands, ensuring a single broker instance is reused rather than recreated on every run.
This module lives in plugins/codex/scripts/lib/broker-lifecycle.mjs and serves as the central authority for all broker-session handling in the Codex plugin. By storing session state (broker ID, authentication token, endpoint) to disk, it eliminates redundant broker creation and enables features like session resumption and cross-machine transfer.
Core Responsibilities of the broker-lifecycle Module
The module exposes three primary functions that manage the complete lifecycle of a broker session:
| Function | Purpose | Key Behavior |
|---|---|---|
ensureBrokerSession() |
Guarantees a valid session exists | Creates new session if none found; returns session object |
loadBrokerSession() |
Reads persisted session from disk | Parses JSON from deterministic file path; throws on invalid data |
saveBrokerSession(session) |
Persists session to disk | Serializes session object atomically to prevent corruption |
These functions are implemented in broker-lifecycle.mjs and imported by multiple components: app-server.mjs, codex.mjs, session-lifecycle-hook.mjs, and the test suite in runtime.test.mjs.
How broker-lifecycle Manages Broker Sessions
The session management follows a strict deterministic flow designed for reliability across process restarts.
Session Startup and Validation
When the plugin initializes, ensureBrokerSession() serves as the entry point:
// From app-server.mjs – guarantees session before server starts
import { ensureBrokerSession } from "./lib/broker-lifecycle.mjs";
async function startServer() {
const session = await ensureBrokerSession();
// Server now has guaranteed access to valid broker credentials
}
This function implements a fail-safe pattern: it attempts to load an existing session, and only creates a new one when the load fails. This prevents accidental session proliferation.
Session Creation and Persistence
If loadBrokerSession() throws (missing file, corrupted JSON, or schema mismatch), ensureBrokerSession() constructs a fresh session object:
// Example: obtaining a validated broker session
import { ensureBrokerSession } from "./lib/broker-lifecycle.mjs";
async function run() {
const session = await ensureBrokerSession();
console.log("Broker ID:", session.id);
console.log("Current endpoint:", session.endpoint);
// session.token is available for authenticated API calls
}
run();
The new session receives a generated UUID for id, a fresh authentication token, and the default endpoint. It is immediately persisted via saveBrokerSession() before return, ensuring no window exists where a valid session exists only in memory.
Manual Session Updates
Components that refresh tokens or modify endpoint configuration use the explicit load-save pattern:
// Example: persisting a token refresh
import { loadBrokerSession, saveBrokerSession } from "./lib/broker-lifecycle.mjs";
async function refreshToken() {
const session = await loadBrokerSession();
session.token = await getNewTokenFromOAuthProvider();
await saveBrokerSession(session);
// Subsequent plugin commands automatically use refreshed token
}
This pattern appears in codex.mjs, where the Codex client wrapper attaches the broker token from loadBrokerSession() to outgoing requests.
Files That Depend on broker-lifecycle
The module's API is consumed across the plugin architecture, demonstrating its role as a shared dependency:
app-server.mjs– CallsensureBrokerSession()at server startup to guarantee session availability for the entire process lifetimecodex.mjs– ImportsloadBrokerSessionto attach broker authentication tokens to Codex API requestssession-lifecycle-hook.mjs– Triggers session validation before each Codex command executiontests/runtime.test.mjs– ExercisesloadBrokerSessionandsaveBrokerSessionto verify persistence across simulated restarts
Testing Session Persistence
The module's behavior is validated through restart simulation:
// From runtime.test.mjs – verifying session survives process restart
import {
loadBrokerSession,
saveBrokerSession,
} from "../plugins/codex/scripts/lib/broker-lifecycle.mjs";
test("session persists across loads", async () => {
const original = await loadBrokerSession();
original.foo = "bar";
await saveBrokerSession(original);
const reloaded = await loadBrokerSession();
expect(reloaded.foo).toBe("bar");
});
This test confirms that the serialization-deserialization roundtrip preserves all session properties, including ad-hoc extensions.
Design Rationale: Why Centralize Session Management?
The broker-lifecycle module prevents three specific failure modes that would occur with distributed session handling:
- Race conditions – Concurrent commands cannot create duplicate broker instances because
ensureBrokerSession()serializes access through filesystem state - State drift – Token refreshes in one component automatically propagate to others via shared persistence
- Orphaned brokers – Explicit session tracking enables intentional cleanup rather than leaving brokers active indefinitely
The deterministic file location (relative to the plugin's working directory) also enables "transfer session to another machine" workflows by copying the session JSON.
Summary
- The broker-lifecycle module (
broker-lifecycle.mjs) centralizes all broker session operations in the OpenAI Codex plugin ensureBrokerSession()guarantees a valid session exists, creating one only when necessaryloadBrokerSession()andsaveBrokerSession()provide explicit persistence control for components that modify session state- The module enables session resumption across plugin commands and cross-machine transfer through deterministic file-based storage
- All major components—
app-server.mjs,codex.mjs,session-lifecycle-hook.mjs—depend on this module for consistent broker session access
Frequently Asked Questions
What happens if the broker session file is corrupted?
loadBrokerSession() throws an error when parsing fails or required fields are missing. ensureBrokerSession() catches this exception and creates a fresh session with new credentials, which is immediately persisted to replace the corrupted file.
Can multiple plugin commands run simultaneously with the same session?
Yes. Because the session is stored on disk, concurrent processes read the same broker ID and token. However, token refresh operations should be serialized to prevent race conditions where one process overwrites another's fresh token.
How does broker-lifecycle differ from session-lifecycle-hook.mjs?
broker-lifecycle.mjs is the storage and retrieval layer—it knows how to read and write session state. session-lifecycle-hook.mjs is the trigger layer—it invokes broker-lifecycle functions at specific points in command execution. The hook depends on the module, not vice versa.
Where is the session file stored on disk?
The module uses a deterministic path relative to the plugin's working directory, typically in a subdirectory of plugins/codex/. The exact path is encapsulated within broker-lifecycle.mjs and not exposed to consuming code, ensuring consistent location across all imports.
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 →