Skip to content

boji1334/codex-session-sync

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Codex 登录方式切换后本地会话不可见问题记录

问题描述

在 Codex Desktop / Codex CLI 中,如果在两种登录方式之间切换:

  • OpenAI 账号登录
  • 自定义 OpenAI-compatible API 登录,例如 https://cat.api.boji1334.com

切换完成后,原来的聊天会话可能会从侧边栏或会话列表中消失。

目前观察到的现象更像是“会话没有丢失,只是当前登录方式 / provider 下没有被索引或展示出来”。本地的 rollout 文件和 sqlite 索引仍然存在。

最简单步骤

只记一句话:先切到你要用的登录模式,再同步会话,最后打开 Codex。

Windows

API 登录:

  1. 关闭 Codex,确保后台没有 Codex 进程。

  2. 打开 CC Switch Codex Setup

  3. 按页面提示安装 CC Switch,输入 sub2api 地址和 API Key,一键导入并保存配置。

  4. 如果你的 sub2api 平台要求 provider 名为 sub2api,确认 config.toml 里是 model_provider = "sub2api"

  5. 运行:

    cd path\to\codex-session-sync
    .\codex-unify-sessions.bat
  6. 打开 Codex。

账号登录:

  1. 打开 Codex,完成账号登录。

  2. 关闭 Codex。

  3. 运行:

    cd path\to\codex-session-sync
    .\codex-unify-sessions.bat
  4. 再打开 Codex。

macOS / Linux

API 登录:

  1. 关闭 Codex,确保后台没有 Codex 进程。

  2. 打开 CC Switch Codex Setup

  3. 按页面提示安装 CC Switch,输入 sub2api 地址和 API Key,一键导入并保存配置。

  4. 如果你的 sub2api 平台要求 provider 名为 sub2api,确认 config.toml 里是 model_provider = "sub2api"

  5. 运行:

    cd /path/to/codex-session-sync
    sh ./codex-unify-sessions.sh
  6. 打开 Codex。

账号登录:

  1. 打开 Codex,完成账号登录。

  2. 关闭 Codex。

  3. 运行:

    cd /path/to/codex-session-sync
    sh ./codex-unify-sessions.sh
  4. 再打开 Codex。

脚本支持 Windows、macOS、Linux。Windows 用 .bat,macOS/Linux 用 .sh,底层都是同一个 Python 合并逻辑。

同步脚本会自动读取当前 config.tomlmodel_provider。如果你的 sub2api 部署固定使用 sub2api,就保持 model_provider = "sub2api",不要切成别的 provider 名。

复现步骤

  1. 使用 OpenAI 账号登录 Codex,创建几个聊天会话。

  2. 退出或切换到自定义 API provider。

  3. 示例配置:

    model_provider = "custom"
    
    [model_providers.custom]
    name = "custom"
    base_url = "https://cat.api.boji1334.com"
    wire_api = "responses"
    requires_openai_auth = true
  4. 重启 Codex 或刷新会话列表。

  5. 观察:之前 OpenAI 账号登录时创建的会话不再显示,或者只显示当前 provider 下创建的会话。

  6. 再切回 OpenAI 账号登录时,也可能出现另一批会话不可见。

预期行为

本地聊天会话应该和具体模型 provider 解耦。

用户切换登录方式或 API base URL 后,仍然应该能看到同一个本地工作区下的历史会话。会话可以显示创建时使用的 provider,但不应该因为当前 provider 不同而从列表里消失。

实际行为

会话似乎按当前登录方式、provider 或 account scope 被分桶展示。

结果是:

  • 用户会误以为历史聊天被删除。
  • 但本地文件仍然存在。
  • 只有当前 provider / account 能索引到的会话会出现在 UI 里。

本地数据位置

Codex 的本地会话通常在这些位置:

Windows:

$env:USERPROFILE\.codex\sessions
$env:USERPROFILE\.codex\archived_sessions
$env:USERPROFILE\.codex\state_5.sqlite
$env:USERPROFILE\.codex\session_index.jsonl

macOS / Linux:

~/.codex/sessions
~/.codex/archived_sessions
~/.codex/state_5.sqlite
~/.codex/session_index.jsonl

其中:

  • sessions/ 保存未归档会话的 rollout JSONL。
  • archived_sessions/ 保存归档后的 rollout JSONL。
  • state_5.sqlite 里的 threads 表保存会话索引。
  • threads 表包含 model_providersourcecwdtitlerollout_patharchived 等字段。

本机检查时,threads.rollout_path 指向的 JSONL 文件仍然存在,说明会话正文没有丢失。

临时找回办法

先备份整个 Codex 目录:

Copy-Item "$env:USERPROFILE\.codex" "$env:USERPROFILE\.codex.backup" -Recurse

然后可以确认会话文件是否还在:

Get-ChildItem "$env:USERPROFILE\.codex\sessions" -Recurse -Filter "*.jsonl"
Get-ChildItem "$env:USERPROFILE\.codex\archived_sessions" -Recurse -Filter "*.jsonl"

如果只是 UI 中看不到,会话通常还能从 JSONL 文件或 sqlite 索引中恢复。不要删除 .codex 目录,也不要覆盖 state_5.sqlite

本地自动合并方案

这个仓库提供了一键合并脚本。

Windows:

.\codex-unify-sessions.bat

macOS / Linux:

sh ./codex-unify-sessions.sh

所有系统通用的 Python 兜底命令:

python tools/merge_codex_sessions.py --apply

如果系统里 Python 命令叫 python3

python3 tools/merge_codex_sessions.py --apply

它会自动读取当前 Codex 模式:

  • 如果当前有 config.toml 且里面写了 model_provider,就把所有本地会话合并到这个 provider。
  • 如果当前是账号登录模式,没有 config.toml,就按 openai 合并。

执行前建议先关闭 Codex,执行完重新打开 Codex。脚本只修改 state_5.sqlite 的会话索引,不修改 sessions/**/*.jsonlarchived_sessions/**/*.jsonl 聊天正文。

安全策略:

  • 写入前会用 sqlite backup API 备份 state_5.sqlite
  • 备份会放在 ~/.codex/session-sync-backups/<时间>/
  • 写入前会执行 PRAGMA quick_check
  • 写入前会检查 threads 表结构是否匹配。
  • 写入事务提交前会确认 threads 数量没有减少。
  • 写入事务提交前会确认扫描到的 rollout 会话都还在索引里。
  • 如果任何一步失败,脚本会退出,不会强行写入。

如果合并后想恢复,关闭 Codex,把备份目录里的 state_5.sqlite 复制回 ~/.codex/state_5.sqlite 即可。聊天正文 JSONL 没有被改过,所以不会因为这个脚本丢失。

底层 Python 脚本也可以单独预览:

python .\tools\merge_codex_sessions.py

默认是预览模式,不会修改任何文件。它会做三件事:

  1. 扫描 ~/.codex/sessions~/.codex/archived_sessions
  2. 检查 state_5.sqlite 里的 threads 索引有没有缺失或归档路径变化。
  3. 统计不同 model_provider 下的会话数量,并计算需要合并多少条。

确认无误后执行:

python .\tools\merge_codex_sessions.py --apply

执行时脚本会先备份 state_5.sqlite,然后:

  • 补齐缺失的会话索引。
  • 修复已归档会话的 rollout_path
  • 把所有本地会话的 model_provider 改成当前配置里的 provider。

如果当前是账号登录,且没有 config.toml,脚本会按 openai 处理:

python .\tools\merge_codex_sessions.py --apply --provider openai

如果当前是自定义 API 登录,可以指定 provider 名称:

python .\tools\merge_codex_sessions.py --apply --provider boji1334

这样切换到账号登录时跑一次 --provider openai,切换到 API 登录时跑一次当前 API provider,例如 CC Switch 默认的 --provider boji1334,两边看到的就是同一批本地聊天记录。

如果你已经有自己的切换脚本,可以在切换完成后调用同步脚本:

  • 账号登录后执行 .\codex-unify-sessions.bat --provider openai
  • API 登录后执行 .\codex-unify-sessions.bat,让它自动读取 CC Switch 写入的 provider。
  • 如果要手动指定,CC Switch 默认是 .\codex-unify-sessions.bat --provider boji1334

建议修复方向

建议上游在会话列表和索引层做以下改动:

  1. 会话列表默认展示所有本地 provider 的会话,而不是只展示当前 provider。
  2. UI 中增加 provider 过滤器,例如 Allopenaicustom api
  3. threads 表可以保留 model_provider 字段作为元数据,但不应该把它作为默认隔离边界。
  4. 切换登录方式后触发一次本地索引重建,从 sessions/archived_sessions/ 扫描 JSONL,补齐 state_5.sqlite.threads
  5. 当当前 provider 与会话创建 provider 不一致时,允许用户打开历史会话,并在继续对话前提示“将使用当前 provider 继续”。

可选的索引重建逻辑

一个安全的修复流程可以是:

  1. 扫描 ~/.codex/sessions/**/*.jsonl~/.codex/archived_sessions/**/*.jsonl
  2. 读取每个 JSONL 的第一条 session_meta
  3. 提取 idcwdsourcemodel_providertimestampcli_version
  4. 从后续消息中生成或保留 titleupdated_athas_user_event
  5. id upsert 到 state_5.sqlite.threads
  6. 不修改原始 rollout 文件。

GitHub Issue 模板

Title:

Local sessions disappear from UI after switching between account login and custom API provider

Body:

### Summary

When switching Codex between OpenAI account login and a custom OpenAI-compatible API provider, existing local chat sessions disappear from the UI. The underlying rollout JSONL files still exist, so this appears to be a session indexing / filtering issue rather than data loss.

### Steps to reproduce

1. Login with an OpenAI account.
2. Create a few Codex conversations.
3. Switch to a custom API provider with a custom `base_url`.
4. Restart Codex or refresh the session list.
5. Observe that previous sessions are no longer visible.

### Expected behavior

Local sessions should remain visible across provider changes. The UI may show which provider created a session, but switching providers should not hide local history by default.

### Actual behavior

Only sessions associated with the current account / provider appear to be listed.

### Local investigation

The local Codex directory still contains rollout files under:

- `~/.codex/sessions`
- `~/.codex/archived_sessions`

The sqlite index at `~/.codex/state_5.sqlite` has a `threads` table with fields including:

- `id`
- `rollout_path`
- `model_provider`
- `cwd`
- `title`
- `archived`

The rollout paths still point to existing files, which suggests the sessions are not lost.

### Suggested fix

Please decouple local session visibility from the current provider by default. A provider filter would be useful, but the default should be `All local sessions`.

It would also help to add a safe local index rebuild operation that scans rollout JSONL files and repopulates missing `threads` rows.

注意事项

不要把下面这些文件直接发到 GitHub:

  • auth.json
  • config.toml 中的 token / key
  • logs_*.sqlite
  • state_*.sqlite
  • sessions/**/*.jsonl
  • archived_sessions/**/*.jsonl

这些文件可能包含 API key、账号信息、聊天正文、项目路径或其他隐私数据。

About

Sync Codex local sessions across account and API provider modes

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors