Keep Codex thread history in one provider bucket.
Homebrew · npm · crates.io · cargo-binstall · GitHub Release
你有没有遇到过这种情况:在 Codex 里切到另一个 model_provider,然后发现之前的会话全不见了?打开 Codex.app,列表空空如也;执行 codex resume,什么都恢复不了。
会话其实还在,只是 Codex 的 SQLite 状态库里每条线程记录了创建它的 provider,切换 provider 之后 Codex 只会显示当前 provider 的线程,其他的就像蒸发了一样。
codex-threadripper 就是为了解决这件事而生的。它会把 Codex 的 SQLite 状态库和 rollout JSONL 首行里的 provider 字段统一收敛到你当前用的那个,这样不管你来回怎么切,codex resume、Codex.app 和 app-server 客户端都能看到完整的历史记录。
- 你会在同一个 Codex 里频繁切换不同的 model_provider
- 你希望所有历史会话在任何 provider 下都能打开和续接
- 你不想每次切完 provider 之后手动处理这个问题
本项目链接并认可 LINUX DO 社区。欢迎在社区讨论帖中交流使用体验、问题和改进建议。
brew tap wangnov/tap
brew install codex-threadrippernpm i -g codex-threadrippercargo binstall codex-threadrippercargo install codex-threadripper从 最新 GitHub Release 下载对应平台的压缩包、安装脚本或 MSI 安装器。
# 先看看现在的情况——有多少线程散落在不同的 provider 桶里
codex-threadripper status
# 立刻做一次收敛(会先备份,放心)
codex-threadripper sync
# 明确把所有历史切到某个 provider 可见桶
codex-threadripper bucket switch cong
# 在前台持续监听,实时处理新线程
codex-threadripper watch
# 装成系统后台服务,以后开机自动跑
codex-threadripper install-servicestatus:查看当前 provider、SQLite 里各 provider 的线程分布,以及后台服务的运行状态sync:立即执行一次收敛。执行前会在 SQLite 状态库旁边的backups/目录里写一份带时间戳的备份;如果 rollout 首行需要改写,也会写 compact journalbucket switch <provider>:把全部历史切到指定 provider 可见桶;首行有 padding 时只做原地 patchbucket prepare:给 rollout 首行补足 JSON 空白 padding,让后续 provider 桶切换保持快速watch:持续监听config.toml的变化,同时定时收敛新增的线程记录print-service-config:打印当前平台的后台服务配置内容(launchd plist / systemd unit / Windows 隐藏 VBS 启动器)install-service:把后台服务装到系统里并立即启动uninstall-service:停止并卸载后台服务
以下旧命令名仍然有效,会自动映射到新命令:
print-plist→print-service-configinstall-launchd→install-serviceuninstall-launchd→uninstall-service
watch 的默认轮询间隔是 500ms。watch、print-service-config 和 install-service 都支持 --poll-interval-ms 来自定义间隔。
所有命令都支持 --provider <provider> 强制指定目标桶,或 --profile <name> 按 Codex v2 profile 读取 $CODEX_HOME/<name>.config.toml 里的 model_provider / sqlite_home。Profile 名称只能包含 ASCII 字母、数字、_ 或 -。如果没有同名 profile 文件,也会兼容旧的 [profiles.<name>] provider 配置。
sync会在 SQLite 状态库旁边的backups/目录里创建备份,然后更新state_5.sqlite里的model_provider字段sync/bucket switch也会按需改写 rollout JSONL 首行里的 provider 可见桶,并写入 compact journal;改写后会恢复原本的文件访问时间和修改时间,避免 Codex.app 的最近会话排序被工具污染watch在运行期间会持续处理新写入的线程记录,保持数据库与 rollout 首行里的 provider 可见桶和当前 provider 对齐--sqlite-only只更新 SQLite,适合只关心数据库索引的场景;当前 Codex.app 也会读取 rollout JSONL 元数据,所以日常可见性修复不建议使用它- 默认状态库路径是
CODEX_HOME/state_5.sqlite;如果 Codex 配置了sqlite_home或环境变量CODEX_SQLITE_HOME,codex-threadripper会跟随 Codex 使用对应目录下的state_5.sqlite
status、sync、watch在任何能访问 Codex SQLite 状态库和 rollout JSONL 的环境下都能用- macOS 后台服务使用
launchd - Linux 后台服务使用
systemd --user(没有 systemd 时会退回到独立的后台进程) - Windows 后台服务使用启动文件夹里的隐藏 VBS 启动器,登录后不会弹出控制台窗口
- 发布的二进制覆盖 Apple Silicon macOS、Intel macOS、Linux x64、Linux ARM64、Windows x64
- CLI 界面同时支持简体中文和英文,根据系统语言自动切换
cargo run -- --helpHere's a situation you might recognize: you switch model_provider in Codex, and suddenly your session list is empty. codex resume finds nothing. The Codex app shows a blank slate.
Your sessions aren't gone. They're just filed under a different provider in Codex's SQLite state DB. Codex only shows threads that match the active provider, so anything created under a different one becomes effectively invisible.
codex-threadripper fixes this by rewriting the model_provider field on every thread row in Codex's SQLite state DB and in the first line of each rollout JSONL to match whichever provider you have active right now. After that, codex resume, Codex.app, and app-server clients all see the full history — no matter how many times you've switched.
- You switch between multiple
model_providervalues in the same Codex home - You want thread history to follow you across provider switches, not stay locked to the provider that created each session
- You'd rather have this handled quietly in the background than think about it
This project links back to and recognizes the LINUX DO community. Feedback, usage notes, and improvement ideas are welcome in the community discussion thread.
brew tap wangnov/tap
brew install codex-threadrippernpm i -g codex-threadrippercargo binstall codex-threadrippercargo install codex-threadripperGrab the right archive, installer script, or MSI from the latest GitHub Release.
# See how your threads are currently distributed across providers
codex-threadripper status
# Reconcile everything right now (a backup is written first)
codex-threadripper sync
# Explicitly move all history into one provider visibility bucket
codex-threadripper bucket switch cong
# Keep watching in the foreground, handling new threads as they arrive
codex-threadripper watch
# Or install it as a background service so it just runs from now on
codex-threadripper install-servicestatus: show the active provider, the per-provider thread counts from SQLite, and whether the background service is runningsync: reconcile once right now, writing a timestamped backup to thebackups/directory beside the SQLite state DB; rollout first-line changes also get a compact journalbucket switch <provider>: move all history into the requested provider visibility bucket; prepared first lines are patched in placebucket prepare: reserve JSON whitespace padding in rollout first lines so future provider bucket switches stay fastwatch: keep watchingconfig.tomlfor provider changes and periodically reconcile any newly added thread rowsprint-service-config: print the platform-specific service config (launchd plist, systemd unit, or Windows hidden VBS launcher) without installing itinstall-service: write the service config and start the serviceuninstall-service: stop and remove the service
These legacy command names still work:
print-plist→print-service-configinstall-launchd→install-serviceuninstall-launchd→uninstall-service
watch polls every 500ms by default. You can change that with --poll-interval-ms on watch, print-service-config, and install-service.
Every command accepts --provider <provider> to force the target bucket, or --profile <name> to resolve model_provider / sqlite_home from Codex's v2 $CODEX_HOME/<name>.config.toml profile. Profile names must contain only ASCII letters, digits, _, or -. If that profile file is missing, legacy [profiles.<name>] provider config is still supported.
syncwrites a backup next to the SQLite state DB and then updates themodel_providercolumn instate_5.sqlitesync/bucket switchalso rewrite the provider visibility bucket in rollout JSONL first lines when needed and write a compact journal; after each rewrite, the original file access and modification times are restored so Codex.app's recent-thread ordering is not polluted by the toolwatchkeeps both SQLite and rollout first-line provider buckets aligned with the active provider as new threads are written--sqlite-onlyupdates SQLite only. Use it only when you deliberately do not need rollout JSONL metadata; current Codex.app builds also read rollout metadata for visibility- The default state DB is
CODEX_HOME/state_5.sqlite; if Codex usessqlite_homeorCODEX_SQLITE_HOME,codex-threadripperfollows that directory and uses itsstate_5.sqlite
status,sync, andwatchwork anywhere you can access Codex's SQLite state DB and rollout JSONL files- macOS uses
launchd - Linux uses
systemd --user, falling back to a detached process when systemd isn't available - Windows uses a hidden VBS launcher in the Startup folder, so no console window appears on login
- Prebuilt binaries are available for Apple Silicon macOS, Intel macOS, Linux x64, Linux ARM64, and Windows x64
- The CLI detects your system language and switches between Simplified Chinese and English automatically
cargo run -- --help