How codex-plugin-cc Manages State Separately from Codex Internal Configuration

codex-plugin-cc maintains its own persistent JSON state independent of Codex's internal configuration, reading Codex settings via the App-Server API but never modifying them.

The openai/codex-plugin-cc repository implements a strict architectural boundary between plugin-specific persistence and the Codex CLI's core configuration system. While the plugin tracks its own flags and job history in a local JSON file, it queries Codex's internal settings—such as provider IDs and authentication tokens—through the App-Server RPC API.

Understanding the State Separation Architecture

The relationship between codex-plugin-cc state and Codex internal configuration is designed to be strictly one-directional. The plugin maintains complete autonomy over its own persistence layer while treating Codex's configuration as read-only external data.

Plugin State lives in a JSON file managed entirely by the plugin's own lifecycle methods. Codex Internal Configuration resides within the Codex installation directory (~/.codex) and runtime memory, exposed only through authenticated API endpoints. This separation ensures that plugin operations cannot corrupt Codex's core authentication or provider settings, while allowing the plugin to adapt its behavior based on Codex's current operational mode.

Where codex-plugin-cc Stores Its State

The plugin persists its data in a JSON file located under a directory determined by the CLAUDE_PLUGIN_DATA environment variable, falling back to $TMPDIR/codex-companion if unset. According to the source code in plugins/codex/scripts/lib/state.mjs, this state file contains:

  • A version field for migration tracking
  • A lightweight config object (including the stopReviewGate boolean)
  • A capped array of recent jobs for resume functionality

The module exports functions like loadState(), saveState(), setConfig(), and upsertJob() to manage this persistence. When you invoke loadState(cwd), the system either reads the existing state.json or initializes a default structure, ensuring the plugin can resume work across CLI invocations without touching Codex's internal files.

How Codex Internal Configuration Works

Codex's internal configuration—including provider settings, authentication tokens, model-selection parameters, and broker endpoint details—is stored in the user's Codex configuration directory and accessed exclusively through the App-Server API. As implemented in plugins/codex/scripts/lib/codex.mjs, helper functions like getCodexAuthStatus(), getCodexAvailability(), and getSessionRuntimeStatus() query endpoints such as account/read and config/read to retrieve current operational parameters.

This configuration layer determines how Codex communicates with models, which authentication methods are required, and whether shared broker sessions are being reused. The plugin never writes to these settings; it merely consumes them via the RPC client defined in plugins/codex/scripts/lib/app-server.mjs.

Reading Codex Configuration from the Plugin

The plugin interacts with Codex's internal configuration strictly as a read-only consumer. By calling getCodexAuthStatus(process.cwd()), the plugin obtains critical details like provider, requiresOpenaiAuth, and availability status, then uses this information to conditionally adjust its own behavior.

For example, if the Codex configuration indicates that OpenAI authentication is required, the plugin might automatically disable its review gate by updating its own state via setConfig(cwd, "stopReviewGate", true). This demonstrates the unidirectional flow: Codex configuration influences plugin state, but plugin state never influences Codex configuration.

Practical Implementation Examples

Managing Plugin State Locally

import {
  loadState,
  setConfig,
  upsertJob,
  resolveStateFile
} from "./plugins/codex/scripts/lib/state.mjs";

const cwd = process.cwd();

// Load current state (creates default if missing)
const state = loadState(cwd);
console.log("Current config:", state.config);

// Update plugin-specific flag
setConfig(cwd, "stopReviewGate", true);

// Track a new job
upsertJob(cwd, {
  id: generateJobId(),
  description: "Run lint",
  createdAt: new Date().toISOString()
});

Source: plugins/codex/scripts/lib/state.mjs defines the state management API.

Querying Codex Internal Configuration

import { getCodexAuthStatus } from "./plugins/codex/scripts/lib/codex.mjs";

(async () => {
  const authInfo = await getCodexAuthStatus(process.cwd());
  console.log("Provider:", authInfo.provider);
  console.log("Requires OpenAI auth:", authInfo.requiresOpenaiAuth);
})();

Source: plugins/codex/scripts/lib/codex.mjs implements the App-Server client wrappers.

Combining Both Systems

import { getCodexAuthStatus } from "./plugins/codex/scripts/lib/codex.mjs";
import { setConfig } from "./plugins/codex/scripts/lib/state.mjs";

(async () => {
  const auth = await getCodexAuthStatus(process.cwd());
  
  // Adapt plugin behavior based on Codex configuration
  if (auth.requiresOpenaiAuth) {
    await setConfig(process.cwd(), "stopReviewGate", true);
  }
})();

This pattern shows the plugin reading Codex's internal configuration (requiresOpenaiAuth) and writing only to its own isolated state (stopReviewGate), maintaining the strict separation between the two systems.

Summary

  • codex-plugin-cc maintains independent persistent state in a JSON file managed by plugins/codex/scripts/lib/state.mjs, storing plugin-specific flags and job history.
  • Codex internal configuration resides in ~/.codex and runtime memory, accessed via the App-Server API (account/read, config/read) through plugins/codex/scripts/lib/codex.mjs.
  • The plugin reads Codex configuration to make operational decisions but never writes to Codex's internal settings.
  • Codex cannot access the plugin's state.json, ensuring complete isolation between the plugin's persistence layer and Codex's core configuration.
  • Environment variable CLAUDE_PLUGIN_DATA controls the plugin's state directory, while Codex uses its own fixed configuration paths.

Frequently Asked Questions

Does codex-plugin-cc modify Codex's internal configuration?

No. The plugin only reads Codex's internal configuration through the App-Server API using functions like getCodexAuthStatus(). It never writes to Codex's configuration files or modifies provider settings, authentication tokens, or model parameters. All mutations are restricted to the plugin's own state.json file.

Where is codex-plugin-cc state stored?

The plugin stores its state in a JSON file within a directory specified by the CLAUDE_PLUGIN_DATA environment variable, or falls back to $TMPDIR/codex-companion if the variable is unset. The specific file path is resolved by resolveStateFile() in plugins/codex/scripts/lib/state.mjs, typically resulting in state.json inside that directory.

How does the plugin access Codex authentication status?

The plugin queries Codex's authentication status by calling getCodexAuthStatus(cwd) from plugins/codex/scripts/lib/codex.mjs, which internally communicates with the Codex App-Server via RPC calls to endpoints like account/read. This returns details including the current provider, whether OpenAI authentication is required, and session availability without exposing sensitive tokens directly to the plugin code.

Can Codex read the plugin's state.json file?

No. Codex's internal systems have no awareness of the plugin's state file location or format. The state.json file is managed exclusively by the plugin's own modules (loadState, saveState), and Codex never references this data. This ensures that plugin-specific implementation details cannot interfere with Codex's core functionality.

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 →