PowerShell utilities for repairing, moving, exporting, importing, shortcut-launching, proxy-enabling, and handling Windows sandbox-helper dialogs for local Codex Desktop sessions on Windows.
These scripts were written around real recovery cases where Codex Desktop still had session JSONL files on disk, but the UI stopped showing projects or threads after a restart, project move, or workspace reset.
- Move sessions from an old project path to a new project path.
- Import exported session JSONL files back into
$HOME\.codex\sessions. - Rebuild Codex Desktop project/thread UI state when sessions exist but projects are missing.
- Move one projectless thread into a specific project.
- Set, update, or clear Codex proxy variables in
~\.codex\.env. - Create a Codex Desktop shortcut that launches with Chromium proxy arguments.
- Close and log the Codex Windows sandbox setup error dialog as a temporary workaround.
| Script | Use it when |
|---|---|
export-codex-sessions.ps1 |
You have sessions under an old cwd and want to export copies, optionally rewriting paths to a new project root. |
import-codex-sessions.ps1 |
You have an export directory containing sessions/*.jsonl and want to restore those files into Codex's session tree. |
restore-codex-projects-and-sessions.ps1 |
Session files already exist locally, but Codex Desktop does not show the expected projects or thread workspace hints. |
move-codex-thread-to-project.ps1 |
One specific thread ID is projectless or attached to the wrong project. |
set-codex-proxy-env.ps1 |
Set, update, or clear Codex proxy variables in ~\.codex\.env without changing unrelated entries. |
create-codex-proxy-shortcut.ps1 |
You want a .lnk shortcut that starts Codex Desktop with --proxy-server=.... |
close-codex-sandbox-error-dialog.ps1 |
You need a temporary watcher that closes the Codex Windows sandbox setup error dialog and prints window/process/control diagnostics. |
| Skill | Use it when |
|---|---|
skills/codex-session-title-repair |
Codex Desktop shows older sessions as "New chat" after restart even though opening them reveals the real title. |
- Close Codex Desktop before running scripts that modify
$HOME\.codex, especiallymove-codex-thread-to-project.ps1. - Start with
-DryRunwhenever the script supports it. - Keep the generated backup directories until you have reopened Codex Desktop and confirmed the UI is correct.
- Use exact Windows path spelling for
OldCwdwhen exporting. Path matching in PowerShell can be case-insensitive, but text rewriting is case-sensitive. - Read files with explicit UTF-8 in Windows PowerShell when checking Chinese content:
Get-Content -LiteralPath .\README_zh.md -Encoding UTF8Use this when a project moved and existing sessions still point at the old cwd.
First preview matched sessions:
.\export-codex-sessions.ps1 `
-OldCwd "C:\Users\<you>\Desktop\old-project" `
-NewCwd "C:\Users\<you>\Desktop\new-project" `
-OutputDir "C:\Users\<you>\Desktop\new-project\.codex-conversations" `
-DryRunThen export:
.\export-codex-sessions.ps1 `
-OldCwd "C:\Users\<you>\Desktop\old-project" `
-NewCwd "C:\Users\<you>\Desktop\new-project" `
-OutputDir "C:\Users\<you>\Desktop\new-project\.codex-conversations" `
-ForceOptional export controls:
-IncludeArchivedalso scans$HOME\.codex\archived_sessions.-IncludeTextMatch "text"exports sessions whose file content contains the text even whencwdis notOldCwd.-NoPathRewritecopies matched sessions without replacingOldCwdwithNewCwd.
Preview the import:
.\import-codex-sessions.ps1 `
-ExportDir "C:\Users\<you>\Desktop\new-project\.codex-conversations" `
-ExpectedCwd "C:\Users\<you>\Desktop\new-project" `
-RegisterProjectRoots `
-DryRunImport and register the project roots:
.\import-codex-sessions.ps1 `
-ExportDir "C:\Users\<you>\Desktop\new-project\.codex-conversations" `
-ExpectedCwd "C:\Users\<you>\Desktop\new-project" `
-RegisterProjectRoots `
-Forceimport-codex-sessions.ps1 writes files into $HOME\.codex\sessions\yyyy\mm\dd based on each rollout-*.jsonl filename. If a target file already exists, -Force is required. Existing files are backed up unless -NoBackup is used. When -RegisterProjectRoots is used, missing project directories throw unless -SkipMissingProjectRoots is also passed.
Useful filters:
.\import-codex-sessions.ps1 -ExportDir ".\.codex-conversations" -OnlyIds "019e..." -DryRun
.\import-codex-sessions.ps1 -ExportDir ".\.codex-conversations" -OnlyFiles "rollout-2026-06-04T04-50-57-019e....jsonl" -DryRunRestore from an import backup:
.\import-codex-sessions.ps1 `
-RestoreBackup "C:\path\to\backup-before-import-20260604-050227"Use this when session files are already present in $HOME\.codex\sessions, but Codex Desktop does not show the projects after restart.
Register explicit projects:
.\restore-codex-projects-and-sessions.ps1 `
-ProjectRoots "C:\Users\<you>\Desktop\codex\project-a", "C:\Users\<you>\Desktop\codex\project-b" `
-DryRunThen run without -DryRun:
.\restore-codex-projects-and-sessions.ps1 `
-ProjectRoots "C:\Users\<you>\Desktop\codex\project-a", "C:\Users\<you>\Desktop\codex\project-b"Or derive project roots from existing session metadata. Only cwd values that still exist as directories are registered:
.\restore-codex-projects-and-sessions.ps1 -ProjectRootsFromSessions -DryRunThis script updates $HOME\.codex\.codex-global-state.json by ensuring:
thread-workspace-root-hintselectron-saved-workspace-rootsactive-workspace-rootsproject-order
It creates a backup directory under $HOME\.codex before writing.
Use this when a single thread ID is projectless or attached to the wrong project.
Important: run this after fully quitting Codex Desktop, including tray/background processes. If Codex is still running, it may rewrite .codex-global-state.json from its in-memory state and undo the project assignment.
Set-Location -LiteralPath "C:\Users\<you>\Desktop\codex-session-tools"
.\move-codex-thread-to-project.ps1 `
-ThreadId "00000000-0000-0000-0000-000000000000" `
-TargetProjectRoot "C:\Users\<you>\Desktop\codex-session-tools" `
-DryRunAfter checking the dry run, close Codex Desktop and run:
.\move-codex-thread-to-project.ps1 `
-ThreadId "00000000-0000-0000-0000-000000000000" `
-TargetProjectRoot "C:\Users\<you>\Desktop\codex-session-tools"Then restart Codex Desktop.
The script updates:
$HOME\.codex\state_5.sqlite- the first
session_metaline in the thread's rollout JSONL $HOME\.codex\.codex-global-state.json
It also removes that thread from projectless state and backs up the database, global state, and session file before writing.
Set proxy variables in ~\.codex\.env for Codex Desktop:
.\set-codex-proxy-env.ps1 `
-ProxyUrl "http://127.0.0.1:<port>"Defaults:
HTTP_PROXY,HTTPS_PROXY,ALL_PROXY:http://127.0.0.1:<port>NO_PROXY:localhost,127.0.0.1,::1- The script creates
~\.codexwhen needed, updates existing proxy keys, appends missing proxy keys, and leaves unrelated.enventries unchanged.
Clear the same proxy variables from ~\.codex\.env:
.\set-codex-proxy-env.ps1 -ClearPreview changes:
.\set-codex-proxy-env.ps1 -ProxyUrl "http://127.0.0.1:<port>" -DryRun
.\set-codex-proxy-env.ps1 -Clear -DryRunThe output marks each proxy key as Add, Update, Keep, Remove, or Absent so it is clear whether the script will create a new entry, modify an existing entry, leave it unchanged, remove it, or find nothing to remove.
Restart Codex Desktop after setting or clearing these variables so it reloads ~\.codex\.env.
Use this when environment variables are not enough for the desktop UI bootstrap and Codex needs Chromium's proxy flag at process startup.
Preview the shortcut that would be generated:
.\create-codex-proxy-shortcut.ps1 `
-ProxyServer "http://127.0.0.1:<port>" `
-DryRunCreate or update Codex Proxy.lnk in the script directory:
.\create-codex-proxy-shortcut.ps1 `
-ProxyServer "http://127.0.0.1:<port>"Create the shortcut in an existing specific directory:
.\create-codex-proxy-shortcut.ps1 `
-ProxyServer "http://127.0.0.1:<port>" `
-OutputDirectory "C:\path\to\shortcuts"-ShortcutName changes the generated .lnk filename, and -AppId overrides the Windows AppsFolder app ID when needed. -IconTheme Dark or -IconTheme Light explicitly selects the tray icon; the default Auto follows the current user's Windows app theme and falls back to Light when that setting is unavailable.
The script creates a shortcut that starts Codex through its Windows AppsFolder AppID and passes --proxy-server=... with Start-Process -ArgumentList. It does not target a versioned WindowsApps executable path directly. The shortcut icon is resolved from the installed package's app\resources\chatgpt-tray-dark.ico or app\resources\chatgpt-tray-light.ico.
Use this as a temporary workaround when Codex Desktop on Windows shows a codex-windows-sandbox-setup.exe error dialog, such as "The specified module could not be found", during filesystem sandbox helper operations.
The watcher only targets visible standard dialogs (#32770) whose title contains codex-windows-sandbox-setup.exe and whose owning process is codex.exe.
Run in the foreground with diagnostics:
.\close-codex-sandbox-error-dialog.ps1 -IntervalMilliseconds 300 -LogStart hidden in the background:
$p = Start-Process powershell.exe -WindowStyle Hidden -PassThru -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File "C:\Users\<you>\Desktop\codex-session-tools\close-codex-sandbox-error-dialog.ps1" -IntervalMilliseconds 300'
$p.IdStop the watcher:
Stop-Process -Id <PID>This only closes the blocking dialog; it does not fix the underlying sandbox helper launch failure. With -Log, the script prints the timestamp, window handle, owning process, Windows session ID, child controls, and close method before closing.
- The scripts use UTF-8 reads/writes for JSONL and global state files.
move-codex-thread-to-project.ps1uses-PythonExewhen provided, thenCODEX_SESSION_TOOLS_PYTHON, then the system Python at%USERPROFILE%\AppData\Local\Programs\Python\Python313\python.exe, thenpythonfromPATH.create-codex-proxy-shortcut.ps1stores a PowerShell AppsFolder launch command in the generated.lnk; the repository should not track generated shortcut files.git statusmay require a per-command safe directory override if the repository is owned by a different Windows SID:
git -c safe.directory=C:/path/to/codex-session-tools status --short