Codex 切换 API 供应商后旧会话消失?从定位到恢复的完整指南

AI-assisted

最近我把 Codex CLI 从第三方 OpenAI 兼容 API 切换到了 ChatGPT 登录。登录本身很顺利,但随后执行 codex resume 时,过去的会话几乎都不见了。

第一反应很容易是:切换账号或供应商时,Codex 把旧 session 删除了。

实际调查后发现,旧会话并没有丢失。问题出在三个不同层次:

  1. resume 默认会按照当前工作目录过滤;
  2. session picker 使用的索引可能没有完整收录旧 CLI 会话;
  3. 旧 session 保存的第三方 model_provider 已不在当前配置中。

本文整理一套安全、可复用的定位与恢复流程。核心原则只有一句:

/resume 列表里没有,不等于磁盘上的 session 文件不存在。

Codex 的会话到底存在哪里

Codex 通常把会话保存为 JSONL 文件:

1
~/.codex/sessions/YYYY/MM/DD/rollout-时间-SESSION_ID.jsonl

Windows 中常见路径是:

1
C:\Users\<用户名>\.codex\sessions

WSL 中通常是:

1
/home/<用户名>/.codex/sessions

文件名最后一段 UUID 就是 session ID:

1
rollout-2026-07-17T18-13-19-<SESSION_ID>.jsonl

只要这个文件还在而且不是空文件,会话通常就没有真正丢失。

为什么切换供应商后看不到旧会话

原因一:当前工作目录过滤

新版 Codex 的 resume 帮助中有一个关键参数:

1
2
3
4
--all
Show all sessions
disables cwd filtering
shows CWD column

也就是说,普通的:

1
codex resume

默认可能只显示与当前目录匹配的会话。过去从其他项目目录或用户主目录创建的 session 不会出现。

先尝试:

1
codex resume --all

如果还有非交互式会话:

1
codex resume --all --include-non-interactive

原因二:Windows 和 WSL 是两套存储

Windows Codex 与 WSL Codex 不共享 ~/.codex

1
2
Windows → C:\Users\<用户名>\.codex
WSL → /home/<用户名>/.codex

如果以前在 WSL 中使用 Codex,现在却在 Windows PowerShell 中执行 resume,Windows 端不会自动扫描 WSL 的 session。

检查 WSL:

1
2
wsl.exe --list --verbose
wsl.exe -d Ubuntu

进入 WSL 后:

1
find ~/.codex/sessions -type f -name '*.jsonl'

找到 WSL session 后,最好直接在 WSL 中恢复,避免 Windows 与 Linux 路径语义混在一起。

原因三:CODEX_HOME 发生变化

Codex 不一定总是读取默认的 ~/.codex。如果设置过 CODEX_HOME,session 可能位于另一套目录中。

PowerShell 检查:

1
2
3
4
5
6
[pscustomobject]@{
CWD = (Get-Location).Path
HOME = $env:HOME
USERPROFILE = $env:USERPROFILE
CODEX_HOME = $env:CODEX_HOME
} | Format-List

还可以检查用户级和系统级环境变量:

1
2
3
4
5
[pscustomobject]@{
Process_CODEX_HOME = $env:CODEX_HOME
User_CODEX_HOME = [Environment]::GetEnvironmentVariable('CODEX_HOME', 'User')
Machine_CODEX_HOME = [Environment]::GetEnvironmentVariable('CODEX_HOME', 'Machine')
} | Format-List

原因四:Session 索引不完整

Codex 根目录中可能有:

1
session_index.jsonl

磁盘上的 rollout 文件数量可能远多于索引记录数。此时某些 /resume 界面只显示索引内的少量 session,但旧 JSONL 仍然完整保存在磁盘上。

比较两者:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$codexRoot = if ($env:CODEX_HOME) {
$env:CODEX_HOME
} else {
Join-Path $env:USERPROFILE '.codex'
}

$sessionCount = @(
Get-ChildItem -LiteralPath (Join-Path $codexRoot 'sessions') `
-File -Recurse -Filter '*.jsonl'
).Count

$indexFile = Join-Path $codexRoot 'session_index.jsonl'
$indexCount = if (Test-Path -LiteralPath $indexFile) {
@(Get-Content -LiteralPath $indexFile -Encoding UTF8).Count
} else {
0
}

[pscustomobject]@{
SessionFiles = $sessionCount
IndexLines = $indexCount
} | Format-List

不要因为索引不完整就立即重建或覆盖索引。UUID 直接恢复通常更安全。

原因五:旧 Provider 已不存在

这是最容易被忽略的一层。

session 文件首行的 session_meta 会记录创建它时使用的 provider,例如:

1
2
3
custom
third-party-relay
openai

切换 ChatGPT 登录后,当前配置可能已经删除了旧 provider 定义。于是 Codex 找到了 session,却在加载配置阶段失败:

1
2
3
Failed to resume session
failed to load configuration
Model provider `custom` not found

这个错误反而证明 session 文件已经被找到。失败的不是“查找会话”,而是“加载旧 provider”。

安全定位旧 Session

第一步:检查版本和实际可执行文件

1
2
3
4
codex.cmd --version

Get-Command codex -All |
Select-Object CommandType, Name, Source, Path

如果 PowerShell 因执行策略拒绝运行 codex.ps1,不需要为了恢复 session 修改执行策略,直接使用:

1
codex.cmd --version

第二步:检查登录身份

1
2
whoami.exe
codex.cmd login status

如果 login status 与预期不一致,继续比较:

1
2
3
$env:USERPROFILE
$env:HOME
$env:CODEX_HOME

服务账户、沙箱用户和真实桌面用户可能读取不同的认证与 Codex 目录。

不要把完整 auth.json 打印到终端或上传到问题报告。它可能包含 access token 和 refresh token。

第三步:列出全部 Session 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$codexRoot = if ($env:CODEX_HOME) {
$env:CODEX_HOME
} else {
Join-Path $env:USERPROFILE '.codex'
}

$sessionRoot = Join-Path $codexRoot 'sessions'

Get-ChildItem -LiteralPath $sessionRoot `
-File -Recurse -Filter '*.jsonl' |
Sort-Object LastWriteTime -Descending |
Select-Object @{
Name = 'Modified'
Expression = { $_.LastWriteTime.ToString('yyyy-MM-dd HH:mm:ss') }
}, @{
Name = 'Bytes'
Expression = { $_.Length }
}, FullName |
Format-Table -AutoSize

如果文件数量很多、大小正常而且修改时间符合预期,就不要再把问题称为“文件丢失”。下一步应该定位目标 UUID 和 provider。

第四步:读取安全元数据

只读取每个 JSONL 的第一行,不读取对话正文:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Get-ChildItem -LiteralPath $sessionRoot `
-File -Recurse -Filter '*.jsonl' |
ForEach-Object {
try {
$firstLine = Get-Content -LiteralPath $_.FullName `
-TotalCount 1 -Encoding UTF8
$record = $firstLine | ConvertFrom-Json
$meta = $record.payload

[pscustomobject]@{
Modified = $_.LastWriteTime
Bytes = $_.Length
SessionId = $meta.id
Cwd = $meta.cwd
Provider = $meta.model_provider
CliVersion = $meta.cli_version
Source = $meta.source
Path = $_.FullName
}
} catch {
Write-Warning "无法解析:$($_.FullName)"
}
} |
Sort-Object Modified -Descending |
Format-List

有了 SessionIdCwdProvider,恢复路径就清楚了。

三种恢复方法

方法一:显示所有 Session

1
codex.cmd resume --all

适合文件存在、只是默认 cwd 筛选导致列表为空的情况。

方法二:按 UUID 直接恢复

1
codex.cmd resume <SESSION_ID>

这种方法绕过 picker、标题、分页和不完整索引,是最可靠的恢复入口。

方法三:覆盖已经消失的旧 Provider

如果出现:

1
Model provider `custom` not found

而当前已经通过 ChatGPT 登录,可以使用:

1
codex.cmd resume <SESSION_ID> -c model_provider=openai

-c 是一次性命令行覆盖,不会把该值写入全局 config.toml。历史上下文仍然来自旧 session,后续新请求则通过当前 OpenAI/ChatGPT provider 执行。

PowerShell 和 CMD 不要混用

这是恢复过程中另一个常见坑。

PowerShell 提示符一般是:

1
PS C:\项目目录>

完整路径写法:

1
& 'C:\path\to\codex.cmd' resume <SESSION_ID> -c model_provider=openai

CMD 提示符一般是:

1
C:\项目目录>

完整路径写法:

1
"C:\path\to\codex.cmd" resume <SESSION_ID> -c model_provider=openai

如果在 CMD 中复制 PowerShell 命令,会看到:

1
此时不应有 &。

如果在 CMD 中用单引号包裹路径,可能出现:

1
文件名、目录名或卷标语法不正确。

CMD 使用双引号,不使用 PowerShell 的 &

五分钟排查清单

下次再次发生类似问题,可以直接按以下顺序执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 1. 当前环境
codex.cmd --version
codex.cmd login status
whoami.exe
Get-Location

# 2. 当前 Codex 根目录
$codexRoot = if ($env:CODEX_HOME) {
$env:CODEX_HOME
} else {
Join-Path $env:USERPROFILE '.codex'
}
$codexRoot

# 3. Session 数量
Get-ChildItem -LiteralPath (Join-Path $codexRoot 'sessions') `
-File -Recurse -Filter '*.jsonl' |
Measure-Object

# 4. 最近的 Session 文件
Get-ChildItem -LiteralPath (Join-Path $codexRoot 'sessions') `
-File -Recurse -Filter '*.jsonl' |
Sort-Object LastWriteTime -Descending |
Select-Object -First 20 LastWriteTime, Length, FullName

# 5. 关闭 cwd 过滤
codex.cmd resume --all

# 6. UUID 直接恢复
codex.cmd resume <SESSION_ID>

# 7. 旧 provider 不存在时
codex.cmd resume <SESSION_ID> -c model_provider=openai

如果曾经使用 WSL:

1
2
wsl.exe --list --verbose
wsl.exe -d Ubuntu

进入 WSL 后:

1
2
find ~/.codex/sessions -type f -name '*.jsonl'
codex resume --all

不要做什么

在确认磁盘状态前,不要:

  • 删除整个 .codex
  • 重新初始化 Codex Home;
  • 覆盖 sessions 目录;
  • 手工重写未知格式的 session 索引;
  • 将 Windows 与 WSL 的 .codex 相互覆盖;
  • 公开 auth.json 或 API Key;
  • 为一次恢复操作永久改写全局 provider 配置。

如何避免下次再踩坑

  1. 为重要 session 记录项目名、cwd、UUID、原 provider 和 Codex 版本;
  2. 定期备份 ~/.codex/sessions,但不要把 auth.json 提交到 Git;
  3. Windows 和 WSL 的 Codex 数据分开管理;
  4. 同一个项目尽量始终从同一个绝对路径启动 Codex;
  5. 切换供应商前记录 CODEX_HOME 和当前 provider 名称;
  6. 恢复旧会话优先使用一次性 -c,不要先改全局配置。

结语

切换 API 供应商或认证方式后,Codex 旧会话“消失”通常不是数据删除,而是存储位置、cwd 过滤、索引和 provider 配置共同造成的可见性问题。

正确的排查顺序应该是:

1
2
3
4
5
6
7
8
9
确认 rollout 文件是否存在

确认当前 CODEX_HOME 和操作系统环境

读取 session UUID、cwd 和 provider

使用 resume --all 或 UUID 直接恢复

旧 provider 缺失时做一次性 provider 覆盖

只要 rollout .jsonl 文件仍然存在且能够解析,绝大多数这类问题都可以恢复,而不需要删除 .codex、重建 session 或永久修改配置。

Codex 切换 API 供应商后旧会话消失?从定位到恢复的完整指南

https://www.t51n9hua.fun/2026/07/27/codex-session-recovery-blog/

作者

Elpam

发布于

2026-07-27

更新于

2026-07-27

许可协议

评论