Where Is the Codex Plugin State Stored? A Deep Dive into openai/codex-plugin-cc

The Codex plugin stores its runtime state on the local file system under a directory computed by resolveStateDir() in plugins/codex/scripts/lib/state.mjs, using either the CLAUDE_PLUGIN_DATA environment variable or falling back to os.tmpdir()/codex-companion.

The openai/codex-plugin-cc repository persists plugin state locally rather than in cloud storage or memory. Understanding where this state resides is essential for debugging, cleanup, and backup strategies. The location is dynamically calculated based on your workspace root and optional environment overrides.

How resolveStateDir() Computes the Storage Location

The core logic resides in plugins/codex/scripts/lib/state.mjs, where the resolveStateDir() function (lines 29-44) implements a deterministic path resolution strategy.

Normalizing the Workspace Root

The calculation begins by calling resolveWorkspaceRoot() and normalizing the result using fs.realpathSync.native. This canonicalization ensures consistent state lookup regardless of symbolic links or relative path variations, preventing duplicate state directories for the same project accessed through different paths.

The Slug and Hash Pattern

The function generates a unique directory name by combining a slug derived from the workspace name with a 16-character hash of the canonical workspace path. This produces a directory structure like myrepo-1a2b3c4d5e6f7g8h that prevents collisions between different workspaces while remaining deterministic for identical project locations.

Environment Variable Override

The state root follows strict priority rules:

  1. If CLAUDE_PLUGIN_DATA is set, the root becomes $(CLAUDE_PLUGIN_DATA)/state
  2. Otherwise, the plugin falls back to os.tmpdir()/codex-companion

The final state directory path follows the pattern {$stateRoot}/${slug}-${hash}.

Files Inside the State Directory

Within the computed directory, the plugin maintains three distinct file types:

  • state.json – The primary persisted JSON object containing defaultState, active jobs, and configuration flags.
  • jobs/<jobId>.json – Individual JSON payload files for each job.
  • jobs/<jobId>.log – Text log files capturing output for specific job executions.

Programmatic State Management

The same module that resolves paths also handles persistence. The saveState() function (lines 92-115) writes atomic updates to state.json, while resolveStateFile() (lines 46-48) returns the absolute path to this file.

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

// Resolve the directory where the plugin stores its state.
const stateDir = resolveStateDir(process.cwd());
// e.g. "/tmp/codex-companion/myrepo-1a2b3c4d5e6f7g8h"
console.log(stateDir);

// Read the persisted state (or default if none exists).
const current = loadState(process.cwd());
console.log("Current jobs:", current.jobs.length);

// Add a new job entry.
upsertJob(process.cwd(), {
  id: "job-123",
  status: "running",
  command: "npm test",
});

// Update a configuration flag.
setConfig(process.cwd(), "stopReviewGate", true);

// The state is automatically saved to `state.json` inside `stateDir`.

Summary

  • The Codex plugin state lives in a local directory computed by resolveStateDir() in plugins/codex/scripts/lib/state.mjs.
  • The location is either $CLAUDE_PLUGIN_DATA/state or falls back to os.tmpdir()/codex-companion.
  • Directory names combine a workspace slug with a 16-character hash of the canonical path.
  • Actual data resides in state.json, with individual job files and logs stored under the jobs/ subdirectory.
  • All read/write operations are handled by functions in state.mjs, including atomic saves and cleanup logic.

Frequently Asked Questions

What environment variable controls the Codex plugin state location?

Set CLAUDE_PLUGIN_DATA to redirect all state storage to $(CLAUDE_PLUGIN_DATA)/state. When this variable is unset, the plugin defaults to the system temporary directory under codex-companion.

How does the plugin handle concurrent workspace state?

By hashing the canonical workspace path into a 16-character suffix, resolveStateDir() generates unique, deterministic directories for each workspace. This isolation prevents state corruption when running multiple projects on the same machine.

What happens if the state directory is deleted?

The plugin treats missing state as a blank slate. When loadState() cannot find state.json, it returns the defaultState object. Subsequent operations automatically recreate the directory structure and files as needed.

Where are job-specific logs stored?

Individual job logs reside at jobs/<jobId>.log within the resolved state directory, alongside their corresponding JSON payload files at jobs/<jobId>.json.

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 →