codex-threadripper 0.1.8

Human-first CLI that keeps Codex thread history aligned to one provider bucket.
<p align="center">
  <img src="./logo.png" width="220" alt="codex-threadripper logo">
</p>

<h1 align="center">codex-threadripper</h1>

<p align="center">
  Keep Codex thread history in one provider bucket.
</p>

<p align="center">
  <a href="https://github.com/Wangnov/codex-threadripper/releases/latest"><img src="https://img.shields.io/github/v/release/Wangnov/codex-threadripper?logo=github" alt="Latest release"></a>
  <a href="https://crates.io/crates/codex-threadripper"><img src="https://img.shields.io/crates/v/codex-threadripper?logo=rust" alt="Crates.io"></a>
  <a href="https://www.npmjs.com/package/codex-threadripper"><img src="https://img.shields.io/npm/v/codex-threadripper?logo=npm" alt="npm"></a>
  <a href="https://github.com/Wangnov/codex-threadripper/actions/workflows/release-candidate.yml"><img src="https://github.com/Wangnov/codex-threadripper/actions/workflows/release-candidate.yml/badge.svg" alt="Release candidate"></a>
  <a href="https://github.com/Wangnov/codex-threadripper/actions/workflows/release.yml"><img src="https://github.com/Wangnov/codex-threadripper/actions/workflows/release.yml/badge.svg" alt="Release"></a>
  <a href="https://github.com/Wangnov/codex-threadripper/actions/workflows/npm-publish.yml"><img src="https://github.com/Wangnov/codex-threadripper/actions/workflows/npm-publish.yml/badge.svg" alt="npm publish"></a>
  <a href="https://github.com/Wangnov/homebrew-tap"><img src="https://img.shields.io/badge/Homebrew-wangnov%2Ftap-FBB040?logo=homebrew" alt="Homebrew tap"></a>
  <a href="https://github.com/Wangnov/codex-threadripper/blob/main/Cargo.toml"><img src="https://img.shields.io/badge/license-MIT-2ea44f" alt="MIT license"></a>
</p>

<p align="center">
  <a href="#readme-cn">中文</a> · <a href="#readme-en">English</a>
</p>

<p align="center">
  Homebrew · npm · crates.io · cargo-binstall · GitHub Release
</p>

---

<a id="readme-cn"></a>

# 中文

你有没有遇到过这种情况:在 Codex 里切到另一个 model_provider,然后发现之前的会话全不见了?打开 Codex.app,列表空空如也;执行 `codex resume`,什么都恢复不了。

会话其实还在,只是 `state_5.sqlite` 里每条线程记录了创建它的 provider,切换 provider 之后 Codex 只会显示当前 provider 的线程,其他的就像蒸发了一样。

`codex-threadripper` 就是为了解决这件事而生的。它会把 `CODEX_HOME/state_5.sqlite` 里所有线程的 provider 字段统一收敛到你当前用的那个,这样不管你来回怎么切,`codex resume`、Codex.app 和 app-server 客户端都能看到完整的历史记录。

## 适合谁用

- 你会在同一个 Codex 里频繁切换不同的 model_provider
- 你希望所有历史会话在任何 provider 下都能打开和续接
- 你不想每次切完 provider 之后手动处理这个问题

## 安装

### Homebrew

```bash
brew tap wangnov/tap
brew install codex-threadripper
```

### npm

```bash
npm i -g codex-threadripper
```

### cargo-binstall

```bash
cargo binstall codex-threadripper
```

### cargo install

```bash
cargo install codex-threadripper
```

### 直接下载二进制

从 [最新 GitHub Release](https://github.com/Wangnov/codex-threadripper/releases/latest) 下载对应平台的压缩包、安装脚本或 MSI 安装器。

## 快速上手

```bash
# 先看看现在的情况——有多少线程散落在不同的 provider 桶里
codex-threadripper status

# 立刻做一次收敛(会先备份,放心)
codex-threadripper sync

# 在前台持续监听,实时处理新线程
codex-threadripper watch

# 装成系统后台服务,以后开机自动跑
codex-threadripper install-service
```

## 命令说明

- `status`:查看当前 provider、SQLite 里各 provider 的线程分布,以及后台服务的运行状态
- `sync`:立即执行一次收敛。执行前会在 `CODEX_HOME/backups/` 里写一份带时间戳的备份
- `watch`:持续监听 `config.toml` 的变化,同时定时收敛新增的线程记录
- `print-service-config`:打印当前平台的后台服务配置内容(launchd plist / systemd unit / Windows 启动脚本)
- `install-service`:把后台服务装到系统里并立即启动
- `uninstall-service`:停止并卸载后台服务

以下旧命令名仍然有效,会自动映射到新命令:

- `print-plist``print-service-config`
- `install-launchd``install-service`
- `uninstall-launchd``uninstall-service`

`watch` 的默认轮询间隔是 500ms。`watch`、`print-service-config` 和 `install-service` 都支持 `--poll-interval-ms` 来自定义间隔。

## 它会改什么

- `sync` 会在 `CODEX_HOME/backups/` 里创建备份,然后更新 `state_5.sqlite` 里的 `model_provider` 字段
- `watch` 在运行期间会持续处理新写入的线程记录,保持数据库与当前 provider 对齐
- 工具不会动 rollout 文件,每条线程原本是用哪个 provider 创建的,仍然可以从源文件里追溯

## 平台支持

- `status``sync``watch` 在任何能访问 `CODEX_HOME/state_5.sqlite` 的环境下都能用
- macOS 后台服务使用 `launchd`
- Linux 后台服务使用 `systemd --user`(没有 systemd 时会退回到独立的后台进程)
- Windows 后台服务使用启动文件夹里的批处理脚本
- 发布的二进制覆盖 Apple Silicon macOS、Intel macOS、Linux x64、Linux ARM64、Windows x64
- CLI 界面同时支持简体中文和英文,根据系统语言自动切换

## 从源码运行

```bash
cargo run -- --help
```

---

<a id="readme-en"></a>

# English

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 `state_5.sqlite`. 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_HOME/state_5.sqlite` 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.

## Who this is for

- You switch between multiple `model_provider` values 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

## Install

### Homebrew

```bash
brew tap wangnov/tap
brew install codex-threadripper
```

### npm

```bash
npm i -g codex-threadripper
```

### cargo-binstall

```bash
cargo binstall codex-threadripper
```

### cargo install

```bash
cargo install codex-threadripper
```

### Direct binary download

Grab the right archive, installer script, or MSI from the
[latest GitHub Release](https://github.com/Wangnov/codex-threadripper/releases/latest).

## Quick start

```bash
# See how your threads are currently distributed across providers
codex-threadripper status

# Reconcile everything right now (a backup is written first)
codex-threadripper sync

# 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
```

## Commands

- `status`: show the active provider, the per-provider thread counts from SQLite, and whether the background service is running
- `sync`: reconcile once right now, writing a timestamped backup to `CODEX_HOME/backups/` before touching anything
- `watch`: keep watching `config.toml` for provider changes and periodically reconcile any newly added thread rows
- `print-service-config`: print the platform-specific service config (launchd plist, systemd unit, or Windows startup script) without installing it
- `install-service`: write the service config and start the service
- `uninstall-service`: stop and remove the service

These legacy command names still work:

- `print-plist``print-service-config`
- `install-launchd``install-service`
- `uninstall-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`.

## What it changes

- `sync` writes a backup and then updates the `model_provider` column in `state_5.sqlite`
- `watch` keeps that column aligned with the active provider as new threads are written
- Rollout files are never touched, so you can always trace a thread back to its original provider if you need to

## Platforms

- `status`, `sync`, and `watch` work anywhere you can access `CODEX_HOME/state_5.sqlite`
- macOS uses `launchd`
- Linux uses `systemd --user`, falling back to a detached process when systemd isn't available
- Windows uses a startup folder script
- 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

## Run from source

```bash
cargo run -- --help
```