内容
<div align="center">
<img src="assets/logo.svg" width="420" alt="baton">
**传递编码代理之间的任务。**
将任何编码代理会话转换为其他代理。只需一个命令。继续您之前的工作。
[](https://crates.io/crates/baton-mcp)
[](https://www.npmjs.com/package/@kasabeh/baton-mcp)
[](https://github.com/Kaseban/baton/actions/workflows/ci.yml)
[](#supported-formats)
[](#license)
<img src="assets/demo.gif" width="800" alt="baton converting a Claude Code session to opencode">
传递的记录保留了 **14/17** 个具体事实。手写的交接总结保留了 **3/17** 个。具体事实。 [基准测试 ↓](#benchmark)
</div>
---
## 四点钟的问题
四点钟时,Claude Code 说 **"使用限制已达到 - 晚上 10 点重置。"** 您已经进行了三个小时的会话:架构已确定,边缘情况已映射,差异已编写一半。
❌ **没有 baton** - 打开另一个代理并从头开始。重新解释计划。重新阅读文件。重新讨论您已经做出的每个决定。
✅ **使用 baton** - 传递会话并继续:
```sh
baton convert --from claude-code --to opencode session.jsonl --import
# passed baton: claude-code → opencode (1388 messages) → handoff.json
# Imported session: ses_8c4c973a521549e2
opencode -s ses_8c4c973a521549e2 # same conversation, different runner
```
适用于每个方向:切换代理任务中途,尝试对一个难以解决的错误获取第二个意见,将会话从编辑器代理移动到终端代理,或以一种格式存档所有内容。
## 快速开始
```sh
# 零安装运行(下载预编译二进制文件)
npx @kasabeh/baton-mcp --help
# 转换 + 自动导入到目标代理
baton convert --from claude-code --to opencode <session.jsonl> --import
# 查看您机器上的所有会话,跨所有代理
baton list
```
## 支持的格式
| 代理 | 读取 | 写入 | 自动导入 |
|---|:---:|:---:|:---:|
| Claude Code | ✅ | ✅ | — |
| OpenCode | ✅ | ✅ | ✅ `opencode import` |
| Codex CLI | ✅ | ✅ | — |
| Gemini CLI | ✅ | ✅ | — |
| Zed | ✅ | ✅ | — |
| Aider | ✅ | ✅ | — |
| Cursor | ✅¹ | —² | — |
| Continue | ✅ | — | — |
| Cline / Roo | ✅ | —² | — |
¹ Cursor 从导出的 JSON 读取(`sqlite3 state.vscdb "SELECT value FROM ItemTable WHERE key='aiService:chats'"`)
² 不计划:Cursor 和 Cline 在编辑器数据库(SQLite / VS Code globalState)中保持会话状态,没有文件级导入路径。
## 基准测试
携带完整的记录是否优于为下一个代理编写交接总结?我们在一个真实的 3.4 MB Claude Code 会话(两个分支使用相同的模型,只有上下文不同)上进行了测量:
| 会话大小 | baton 记录 | 交接总结 |
|---|---:|---:|
| 小(93 KB) | **3/3** 细节回忆 | 1/3 |
| 中(198 KB) | **6/6** | 1/6 |
| 大(599 KB) | **5/8** | 1/8 |
| **总计** | **14/17** | **3/17** |
总结丢失了具体事实(版本、行数、MSRV),即使在最小的切片中也是如此 - 接收代理必须重新读取文件并重新运行命令来重新发现它们。机械保真度:所有 896 条消息都被写入每个目标; 往返损失反映每个目标格式的表达能力(claude-code 896/896, codex 736, gemini-cli 723, aider 111 - 它只存储聊天文本)。
完整的基准测试方法、注意事项和复现步骤:[benchmark/RESULTS.md](benchmark/RESULTS.md)。
## MCP 服务器
baton 也是一个 MCP 服务器 - 您的代理可以在会话中途传递 baton:
| 工具 | 描述 |
|---|---|
| `list_sessions` | 扫描所有代理,返回统一列表 |
| `convert_session` | 将会话从一种格式转换为另一种 |
| `import_to_target` | 转换并运行目标代理的导入命令 |
| `detect_format` | 嗅探文件/目录并报告生成它的代理 |
```sh
baton install # 在每个检测到的代理的 MCP 配置中注册 baton
baton doctor # 验证
baton uninstall # 从所有代理中删除
```
## 工作原理
```
Claude Code 会话(.jsonl)
│
▼
baton read ──► 标准 Session { messages: [Text, Reasoning, ToolCalls, ToolResult] }
│
▼
baton write ──► OpenCode 导入 JSON(SessionV1 架构)
```
每种代理格式都被读取到**标准中间表示**,然后以目标格式写入。添加新格式为 O(1),而不是每对转换器为 O(N×M)。
## 安装
```sh
# npm(预编译二进制文件,无需 Rust)
npm install -g @kasabeh/baton-mcp
# Homebrew
brew install kaseban/tap/baton-mcp
# Cargo binstall(预编译二进制文件)
cargo binstall baton-mcp
# Cargo(从源代码)
cargo install baton-mcp
# Shell 安装程序(预编译二进制文件)
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/Kaseban/baton/releases/latest/download/baton-mcp-installer.sh | sh
```
或从 [GitHub Releases](https://github.com/Kaseban/baton/releases) 获取二进制文件。
## 构建
```sh
git clone https://github.com/Kaseban/baton.git
cd baton
cargo build --release
./target/release/baton --help
```
## 贡献
每种格式都位于 `src/formats/<name>.rs` 并实现了 `Format` 特征(读取 + 写入)。参见 `src/formats/claude_code.rs` 以获取完整的参考实现。
所有九种格式都有读取器;Claude Code、OpenCode、Codex、Zed、Aider 和 Gemini CLI 也有写入器。现在最有影响力的贡献是一个 **Continue** 的写入器。
不要掉落 baton。
## 许可证
双重许可下 MIT OR Apache-2.0。