
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 客户端都能看到完整的历史记录。
本项目链接并认可 LINUX DO 社区。欢迎在社区讨论帖中交流使用体验、问题和改进建议。
brew tap wangnov/tap
brew install codex-threadripper
npm i -g codex-threadripper
cargo binstall codex-threadripper
cargo 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-service
status:查看当前 provider、SQLite 里各 provider 的线程分布,以及后台服务的运行状态sync:立即执行一次收敛。执行前会在 SQLite 状态库旁边的 backups/ 目录里写一份带时间戳的备份;如果 rollout 首行需要改写,也会写 compact journalbucket switch <provider>:把全部历史切到指定 provider 可见桶;首行有 padding 时原地 patch,旧的冷 rollout 需要扩容时会安全重写并补 paddingbucket prepare:检查 rollout 首行 padding;需要扩容首行的文件会被跳过,避免替换仍可能被 Codex 写入的日志文件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-servicewatch 的默认轮询间隔是 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;有足够 padding 时会原地 patch,旧的冷 rollout 需要扩容时会通过临时文件安全重写并补 padding;刚写过、仍可能被 Codex 写入的 rollout 会被跳过,待稍后重跑。改写后会恢复原本的文件访问时间和修改时间,避免 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.sqlitestatus、sync、watch 在任何能访问 Codex SQLite 状态库和 rollout JSONL 的环境下都能用launchdsystemd --user(没有 systemd 时会退回到独立的后台进程)cargo run -- --help
Here'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.
model_provider values in the same Codex homeThis 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-threadripper
npm i -g codex-threadripper
cargo binstall codex-threadripper
cargo install codex-threadripper
Grab 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-service
status: 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 the backups/ 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 place, while older cold rollouts that need first-line growth are safely rewritten with paddingbucket prepare: inspect rollout first-line padding; files that would require first-line growth are skipped so the tool does not replace logs Codex may still be writingwatch: keep watching config.toml for 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 serviceThese legacy command names still work:
print-plist → print-service-configinstall-launchd → install-serviceuninstall-launchd → uninstall-servicewatch 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.
sync writes a backup next to the SQLite state DB and then updates the model_provider column in state_5.sqlitesync / bucket switch also rewrite the provider visibility bucket in rollout JSONL first lines and write a compact journal. Prepared first lines are patched in place; older cold rollouts that need first-line growth are safely rewritten through a temporary file and padded for future switches; recently written rollouts that Codex may still be writing are skipped and can be retried later. After each rewrite, the original file access and modification times are restored so Codex.app's recent-thread ordering is not polluted by the toolwatch keeps both SQLite and rollout first-line provider buckets aligned with the active provider as new threads are written--sqlite-only updates SQLite only. Use it only when you deliberately do not need rollout JSONL metadata; current Codex.app builds also read rollout metadata for visibilityCODEX_HOME/state_5.sqlite; if Codex uses sqlite_home or CODEX_SQLITE_HOME, codex-threadripper follows that directory and uses its state_5.sqlitestatus, sync, and watch work anywhere you can access Codex's SQLite state DB and rollout JSONL fileslaunchdsystemd --user, falling back to a detached process when systemd isn't availablecargo run -- --help
$ claude mcp add codex-threadripper \
-- python -m otcore.mcp_server <graph>