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:
- If
CLAUDE_PLUGIN_DATAis set, the root becomes$(CLAUDE_PLUGIN_DATA)/state - 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 containingdefaultState, 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()inplugins/codex/scripts/lib/state.mjs. - The location is either
$CLAUDE_PLUGIN_DATA/stateor falls back toos.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 thejobs/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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →