内容
# 会话转换
**转换编码代理会话的MCP服务器,支持Claude Code、Codex CLI和OpenCode。**
唯一支持**OpenCode SQLite**会话转换的工具 — [agent-convert](https://github.com/theoriclabs/agent-convert) 和 [ctxmv](https://github.com/Ryu0118/ctxmv) 处理Claude↔Codex 但不涉及OpenCode的 `.opencode/opencode.db`。
## 解决了什么问题?
您正在使用多个AI编码代理(Claude Code、Codex CLI、OpenCode),并希望**将一个会话从一个代理迁移到另一个** — 也许您在Claude Code中开始,但想在OpenCode中继续,或者您发现了一个很棒的Codex会话,在Claude中会很有用。
每个代理存储会话的方式不同:
- **Claude Code** — `~/.claude/projects/<hash>/<session-id>.jsonl`中的JSONL文件(也支持旧的嵌套`sessions/`)
- **Codex CLI** — `~/.codex/sessions/YYYY/MM/DD/`中的滚动JSONL
- **OpenCode** — 当前的SQLite数据库,位于 `~/.local/share/opencode/opencode.db`;也支持旧的项目本地数据库 `<project>/.opencode/opencode.db`
这个MCP服务器从任何这些读取,标准化为统一格式,然后写入任何其他格式。**所有6个转换方向都有效**(Claude→Codex,Claude→OpenCode,Codex→Claude,Codex→OpenCode,OpenCode→Claude,OpenCode→Codex)。
## 快速开始
```bash
git clone https://github.com/megamen32/session-convert.git
cd session-convert
npm install
npm run build
```
### MCP配置
添加到您的MCP客户端配置(Claude Desktop,Cursor,Windsurf等):
**Claude Desktop** (`claude_desktop_config.json`):
```json
{
"mcpServers": {
"session-convert": {
"command": "node",
"args": ["/绝对路径/to/session-convert/dist/index.js"]
}
}
}
```
**Cursor / Windsurf** (`.cursor/mcp.json` 或等效):
```json
{
"mcpServers": {
"session-convert": {
"command": "node",
"args": ["/绝对路径/to/session-convert/dist/index.js"]
}
}
}
```
## MCP工具
### `list_sessions`
列出来自某个工具的可用会话。按工作目录前缀筛选。
```
list_sessions({ harness: "claude", cwdPrefix: "~/apps" })
list_sessions({ harness: "codex" })
list_sessions({ harness: "opencode", searchPaths: ["~/projects"] })
```
### `convert_session`
按会话ID将一个会话从一个工具转换为另一个。
```
convert_session({ from: "claude", to: "opencode", sessionId: "abc-123" })
convert_session({ from: "codex", to: "claude", sessionId: "xyz-789" })
convert_session({ from: "opencode", to: "codex", sessionId: "oc-session-1", projectPath: "/path/to/project" })
```
### `preview_conversion`
预演转换 — 显示消息分解、工具调用统计和兼容性警告,而不进行任何写入。
```
preview_conversion({ from: "claude", to: "opencode", sessionId: "abc-123" })
```
### `convert_by_path`
按会话文件的直接路径进行转换。自动检测格式(Claude JSONL,Codex滚动JSONL或OpenCode `.db`)。
```
convert_by_path({ sourcePath: "/home/user/.claude/projects/.../sessions/abc.jsonl", to: "codex" })
convert_by_path({ sourcePath: "/home/user/myproject/.opencode/opencode.db", to: "claude" })
```
## 转换矩阵
| 来源/目标 | Claude Code | Codex CLI | OpenCode |
|-----------|:-----------:|:---------:|:--------:|
| **Claude Code** | — | ✅ | ✅ |
| **Codex CLI** | ✅ | — | ✅ |
| **OpenCode** | ✅ | ✅ | — |
## 保留内容
| 内容类型 | Claude → Codex | Claude → OpenCode | Codex → Claude | Codex → OpenCode | OpenCode → Claude | OpenCode → Codex |
|---|---|---|---|---|---|---|
| 文本消息 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 工具调用(名称+参数) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 工具结果 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 思考/推理 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 图片 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 会话元数据(CWD,时间戳) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 模型名称 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Token使用 | 近似 | 近似 | ✅ | 近似 | 近似 | 近似 |
## 工作原理
```
源格式 → 统一对话 → 目标格式
(JSONL/SQLite) (类型消息) (JSONL/SQLite)
```
1. **读取** — 解析源会话(Claude JSONL,Codex滚动JSONL或OpenCode SQLite)为统一的`Conversation`对象,包含类型化的`Message`部分(`text`,`tool_calls`,`tool_result`,`thinking`,`image`)
2. **转换** — 在格式特定的表示之间映射内容类型(例如,Claude的`tool_use` ↔ Codex的`function_call` ↔ OpenCode的双重包装的`tool_calls`部分)
3. **写入** — 序列化为目标工具的原生格式,并存储在正确的位置
### 格式特定细节
- **Claude Code** 将会话存储为 `.jsonl` 文件中的一个JSON对象。工具调用是 `tool_use` 块,结果是下一个用户消息中的 `tool_result` 块。思考块存储为 `thinking` 内容类型。
- **Codex CLI** 使用 `session_meta` 头行,后跟 `response_item` 条目。工具调用是单独的 `function_call` 项,带有匹配的 `function_call_output` 项。推理是一种单独的 `reasoning` 项类型。
- **OpenCode** 目前使用具有 `session`、`message` 和 `part` 表的全局SQLite数据库。较旧的项目本地数据库使用 `sessions` 和 `messages`,部分内容存储为JSON,格式为双重包装: `[{ "type": "text", "data": { "text": "..." } }]` 。支持这两种模式。
## 测试
```bash
# 创建OpenCode SQLite测试fixture
npm run test:fixtures
# 运行所有34个测试(涵盖所有6个转换方向+边缘情况)
npm test
# 监视模式
npm run test:watch
```
测试使用3个手工制作的迷你会话(每个工具一个),包括文本、思考、工具调用和工具结果内容部分。每个测试从fixture读取,写入目标格式,然后读取回以验证往返完整性。
## 已知限制
- **加密Codex推理** (`encrypted_content`) 无法解密 — 仅保留摘要文本
- **Claude子代理会话** (Task工具生成子会话)不会被跟随 — 仅转换父对话
- **Token使用** 在跨转换时是近似的(每个提供者不同的tokenizer)
- **OpenCode** 必须重启以发现新导入的会话
- **系统消息** 被丢弃用于Claude(不存储在JSONL中)或转换为Codex的用户消息
## 与替代方案比较
| 功能 | session-convert | agent-convert | ctxmv |
|---|:---:|:---:|:---:|
| Claude Code 读取/写入 | ✅ | ✅ | ✅ |
| Codex CLI 读取/写入 | ✅ | ✅ | ✅ |
| **OpenCode 读取/写入** | **✅** | ❌ | ❌ |
| MCP 接口 | ✅ | ❌ | ❌ |
| SQLite 支持 | ✅ | ❌ | ❌ |
| 会话预览 | ✅ | ❌ | ❌ |
| 基于路径的转换 | ✅ | ✅ | ❌ |
## 关键词
`mcp server`, `claude code 会话导出`, `codex cli 会话迁移`, `opencode 会话转换`, `ai 编码代理会话转移`, `claude 到 codex`, `claude 到 opencode`, `codex 到 claude`, `opencode 到 claude`, `会话迁移工具`, `编码代理上下文切换`, `mcp 工具`, `模型上下文协议`, `会话转换器`, `ai 代理会话备份`, `claude jsonl`, `codex 滚动jsonl`, `opencode sqlite`, `编码会话可移植性`
## License
MIT