Summary
Codex Desktop can put a project into a split state after using the project rename UI:
- the sidebar display label changes
- the underlying workspace root remains
~/Documents/New project N
- the actual folder on disk remains
~/Documents/New project N
- existing thread rows and rollout metadata continue to reference the old root
The visible result is a sidebar row that shows both the renamed project label and the old autogenerated folder name, for example:
Vera Companio... New proj...
This was reproducible across multiple renamed projects in the same profile, not just one project.
Environment
Observed on:
Codex Desktop: 26.506.31421
Bundle id: com.openai.codex
Platform: macOS arm64
The public repository checked was openai/codex at:
2abdeb3 Read cached metadata for installed Git plugins (#20825)
Why I am filing this here
I am filing this in openai/codex because it is the public repo linked to Codex installs and it contains the app-server, protocol, thread-store, rollout, and state-db code that participate in this bug. However, the Desktop/Electron code that appears to own the project sidebar and global Desktop state does not appear to be present in this public repository.
The public repo README describes this repository primarily as the Codex CLI and points separately to the Desktop app experience:
<strong>Codex CLI</strong> is a coding agent from OpenAI that runs locally on your computer.
...
If you want the desktop app experience, run <code>codex app</code> or visit ...
The installed macOS Desktop app is a packaged Electron application. Extracting the shipped /Applications/Codex.app/Contents/Resources/app.asar shows this package metadata:
{
"name": "openai-codex-electron",
"productName": "Codex",
"version": "26.506.31421",
"main": ".vite/build/bootstrap.js",
"codexBuildFlavor": "prod",
"codexBuildNumber": "2620"
}
The Desktop-specific persisted state keys involved in this bug were present in ~/.codex/.codex-global-state.json and in the shipped Electron bundle, but I could not find them in the public repo checkout. These searches returned no matches in openai/codex:
rg 'electron-workspace-root-labels' openai-codex-src
rg 'electron-saved-workspace-roots' openai-codex-src
rg 'thread-workspace-root-hints' openai-codex-src
rg 'project-order' openai-codex-src
The missing keys matter because the observed split state is created around those Desktop-owned values:
electron-workspace-root-labels old root -> new display label
electron-saved-workspace-roots still contains old root
project-order still contains old root
thread-workspace-root-hints can still point at old/projectless roots
So this issue likely needs Desktop/Electron source changes, not just Rust changes in this repo. If that source lives elsewhere, please route this to the Desktop owner. The public Rust code is still relevant because it explains why stale rollout cwd values can survive and reappear after a partial Desktop-side rename/remap.
Steps to reproduce
- Create or open several Codex Desktop projects that were auto-created as
~/Documents/New project N.
- Create at least one thread in each project.
- Rename the projects from the Desktop UI, for example:
~/Documents/New project 3 -> Hermes agent
~/Documents/New project 4 -> Pinchpoint gateway
~/Documents/New project 5 -> Vera Companion app
- Restart Codex Desktop.
- Observe the project sidebar.
Observed state before repair
The display labels were updated, but the durable roots were not.
{
"electron-workspace-root-labels": {
"/Users/<user>/Documents/New project 3": "Hermes agent",
"/Users/<user>/Documents/New project 4": "Pinchpoint gateway",
"/Users/<user>/Documents/New project 5": "Vera Companion app"
},
"electron-saved-workspace-roots": [
"/Users/<user>/Documents/New project 5",
"/Users/<user>/Documents/New project 4",
"/Users/<user>/Documents/New project 3"
],
"project-order": [
"/Users/<user>/Documents/New project 5",
"/Users/<user>/Documents/New project 4",
"/Users/<user>/Documents/New project 3"
]
}
The folders on disk still existed under the old names:
/Users/<user>/Documents/New project 3
/Users/<user>/Documents/New project 4
/Users/<user>/Documents/New project 5
SQLite threads.cwd also still pointed at the old names:
/Users/<user>/Documents/New project 3 2 threads
/Users/<user>/Documents/New project 4 3 threads
/Users/<user>/Documents/New project 5 9 threads
Rollout JSONL metadata also contained old cwd values:
/Users/<user>/Documents/New project 3 13 session_meta/turn_context cwd records
/Users/<user>/Documents/New project 4 17 session_meta/turn_context cwd records
/Users/<user>/Documents/New project 5 222 session_meta/turn_context cwd records
Relevant public code
The state extraction code treats rollout session_meta and turn_context as thread metadata sources:
codex-rs/state/src/extract.rs
RolloutItem::SessionMeta(_) | RolloutItem::TurnContext(_) => true,
...
if !meta_line.meta.cwd.as_os_str().is_empty() {
metadata.cwd = meta_line.meta.cwd.clone();
}
...
if metadata.cwd.as_os_str().is_empty() {
metadata.cwd = turn_ctx.cwd.clone();
}
There is also an explicit regression test asserting that rollout cwd wins even when SQLite has a different cwd:
codex-rs/thread-store/src/local/read_thread.rs
async fn read_thread_preserves_rollout_cwd_when_sqlite_metadata_exists() {
...
let rollout_cwd = PathBuf::from("/");
...
builder.cwd = home.path().join("sqlite-workspace");
...
assert_eq!(thread.cwd, rollout_cwd);
}
That behavior makes a partial rename/remap fragile. Updating only SQLite or only Desktop global state can still leave old rollout cwd values that are read back later.
The current public app-server metadata update API also does not appear to expose a workspace-root/cwd remap operation. ThreadMetadataUpdateParams only accepts git_info:
codex-rs/app-server-protocol/src/protocol/v2/thread.rs
pub struct ThreadMetadataUpdateParams {
pub thread_id: String,
pub git_info: Option<ThreadMetadataGitInfoUpdateParams>,
}
The request processor also requires gitInfo and builds a Git-only patch:
codex-rs/app-server/src/request_processors/thread_processor.rs
let ThreadMetadataUpdateParams { thread_id, git_info } = params;
...
let Some(ThreadMetadataGitInfoUpdateParams { sha, branch, origin_url }) = git_info else {
return Err(invalid_request("gitInfo must include at least one field"));
};
...
let patch = StoreThreadMetadataPatch {
git_info: Some(StoreGitInfoPatch { ... }),
..Default::default()
};
So, from the public code, there does not seem to be a supported app-server operation for "rename/remap this workspace root and all thread cwd metadata under it."
Expected behavior
Project rename should not leave display label and workspace root split.
At minimum, a project rename should do one of these:
- Rename only the display label and keep the folder/root label in the UI clearly separate.
- Rename/remap the actual workspace root and update all durable path-keyed metadata consistently.
If the Desktop UI presents this as a project rename for an auto-created New project N folder, I would expect option 2.
Suggested fix
Add one supported operation for workspace root rename/remap instead of treating label, root, folder, SQLite metadata, and rollout metadata as separate updates.
Suggested shape:
oldRoot: absolute path
newRoot: absolute path
displayLabel: string
renameFolderOnDisk: boolean
The operation should update, transactionally where possible:
- Desktop saved workspace roots
- project order
- workspace root labels
- thread workspace-root hints
- filesystem folder name, if requested and safe
- SQLite
threads.cwd for threads under the old root
- rollout metadata that can otherwise restore stale
cwd
If rewriting old rollout JSONL is not desirable, an append-only canonical remap record or a state DB override that is guaranteed to win over stale rollout session_meta.cwd would also work. The important part is that restart/reload must not recover the old root.
Local repair that fixed the issue
Closing Codex Desktop and applying a complete remap fixed the UI after restart:
/Users/<user>/Documents/New project 3 -> /Users/<user>/Documents/Hermes agent
/Users/<user>/Documents/New project 4 -> /Users/<user>/Documents/Pinchpoint gateway
/Users/<user>/Documents/New project 5 -> /Users/<user>/Documents/Vera Companion app
The repair updated:
~/.codex/.codex-global-state.json
~/.codex/state_5.sqlite threads.cwd
~/.codex/sessions/**/rollout-*.jsonl session_meta.payload.cwd
~/.codex/sessions/**/rollout-*.jsonl turn_context.payload.cwd
the actual folders under ~/Documents
After repair:
rollout files changed: 14
rollout cwd records changed: 252
old SQLite rows for renamed roots: 0
new SQLite rows:
/Users/<user>/Documents/Hermes agent 2
/Users/<user>/Documents/Pinchpoint gateway 3
/Users/<user>/Documents/Vera Companion app 9
No thread content was changed. Only workspace-root metadata was remapped.
Regression test
Suggested regression coverage:
- Create three projects with auto-generated folder names under
~/Documents/New project N.
- Create at least one thread in each project.
- Rename the projects from the Desktop UI.
- Restart Desktop.
- Assert that the sidebar does not show
New project N for renamed projects.
- Assert that threads still appear under the renamed projects.
- Assert that SQLite
threads.cwd and rollout-derived cwd metadata do not restore the old root after restart.
Related issues
This overlaps with existing path/remap reports, but it is not the same repro:
The distinct issue here is that Codex Desktop's own project rename UI can create the mismatch without the user manually moving the folder first.
Summary
Codex Desktop can put a project into a split state after using the project rename UI:
~/Documents/New project N~/Documents/New project NThe visible result is a sidebar row that shows both the renamed project label and the old autogenerated folder name, for example:
This was reproducible across multiple renamed projects in the same profile, not just one project.
Environment
Observed on:
The public repository checked was
openai/codexat:Why I am filing this here
I am filing this in
openai/codexbecause it is the public repo linked to Codex installs and it contains the app-server, protocol, thread-store, rollout, and state-db code that participate in this bug. However, the Desktop/Electron code that appears to own the project sidebar and global Desktop state does not appear to be present in this public repository.The public repo README describes this repository primarily as the Codex CLI and points separately to the Desktop app experience:
The installed macOS Desktop app is a packaged Electron application. Extracting the shipped
/Applications/Codex.app/Contents/Resources/app.asarshows this package metadata:{ "name": "openai-codex-electron", "productName": "Codex", "version": "26.506.31421", "main": ".vite/build/bootstrap.js", "codexBuildFlavor": "prod", "codexBuildNumber": "2620" }The Desktop-specific persisted state keys involved in this bug were present in
~/.codex/.codex-global-state.jsonand in the shipped Electron bundle, but I could not find them in the public repo checkout. These searches returned no matches inopenai/codex:The missing keys matter because the observed split state is created around those Desktop-owned values:
So this issue likely needs Desktop/Electron source changes, not just Rust changes in this repo. If that source lives elsewhere, please route this to the Desktop owner. The public Rust code is still relevant because it explains why stale rollout
cwdvalues can survive and reappear after a partial Desktop-side rename/remap.Steps to reproduce
~/Documents/New project N.Observed state before repair
The display labels were updated, but the durable roots were not.
{ "electron-workspace-root-labels": { "/Users/<user>/Documents/New project 3": "Hermes agent", "/Users/<user>/Documents/New project 4": "Pinchpoint gateway", "/Users/<user>/Documents/New project 5": "Vera Companion app" }, "electron-saved-workspace-roots": [ "/Users/<user>/Documents/New project 5", "/Users/<user>/Documents/New project 4", "/Users/<user>/Documents/New project 3" ], "project-order": [ "/Users/<user>/Documents/New project 5", "/Users/<user>/Documents/New project 4", "/Users/<user>/Documents/New project 3" ] }The folders on disk still existed under the old names:
SQLite
threads.cwdalso still pointed at the old names:Rollout JSONL metadata also contained old
cwdvalues:Relevant public code
The state extraction code treats rollout
session_metaandturn_contextas thread metadata sources:codex-rs/state/src/extract.rsThere is also an explicit regression test asserting that rollout cwd wins even when SQLite has a different cwd:
codex-rs/thread-store/src/local/read_thread.rsThat behavior makes a partial rename/remap fragile. Updating only SQLite or only Desktop global state can still leave old rollout
cwdvalues that are read back later.The current public app-server metadata update API also does not appear to expose a workspace-root/cwd remap operation.
ThreadMetadataUpdateParamsonly acceptsgit_info:codex-rs/app-server-protocol/src/protocol/v2/thread.rsThe request processor also requires
gitInfoand builds a Git-only patch:codex-rs/app-server/src/request_processors/thread_processor.rsSo, from the public code, there does not seem to be a supported app-server operation for "rename/remap this workspace root and all thread cwd metadata under it."
Expected behavior
Project rename should not leave display label and workspace root split.
At minimum, a project rename should do one of these:
If the Desktop UI presents this as a project rename for an auto-created
New project Nfolder, I would expect option 2.Suggested fix
Add one supported operation for workspace root rename/remap instead of treating label, root, folder, SQLite metadata, and rollout metadata as separate updates.
Suggested shape:
The operation should update, transactionally where possible:
threads.cwdfor threads under the old rootcwdIf rewriting old rollout JSONL is not desirable, an append-only canonical remap record or a state DB override that is guaranteed to win over stale rollout
session_meta.cwdwould also work. The important part is that restart/reload must not recover the old root.Local repair that fixed the issue
Closing Codex Desktop and applying a complete remap fixed the UI after restart:
The repair updated:
After repair:
No thread content was changed. Only workspace-root metadata was remapped.
Regression test
Suggested regression coverage:
~/Documents/New project N.New project Nfor renamed projects.threads.cwdand rollout-derived cwd metadata do not restore the old root after restart.Related issues
This overlaps with existing path/remap reports, but it is not the same repro:
The distinct issue here is that Codex Desktop's own project rename UI can create the mismatch without the user manually moving the folder first.