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

> Discover where the Codex plugin state is stored in the openai/codex-plugin-cc repository. Learn about its local file system storage, CLAUDE_PLUGIN_DATA, and os.tmpdir() fallback for detailed insights.

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

---

**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`](https://github.com/openai/codex-plugin-cc/blob/main/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`](https://github.com/openai/codex-plugin-cc/blob/main/state.json), while `resolveStateFile()` (lines 46-48) returns the absolute path to this file.

```javascript
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`](https://github.com/openai/codex-plugin-cc/blob/main/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`](https://github.com/openai/codex-plugin-cc/blob/main/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`.