前言¶
如果你同时使用 Codex、Claude Code、Pi、Reasonix、OpenCode 和 DSH,会遇到一个具体问题:对话记录分散在各个工具自己的存储里,格式互不兼容。想在 DSH 里继续之前的对话,或者把 DSH 会话交给其他工具接着用,基本只能手工整理。
下面介绍的 dsh-shuttle 解决的就是这个问题。它是一个 DeepSeek Harness 插件,同时提供离线 CLI,在 DSH 与这五类工具之间双向迁移对话记录。DSH 的理念是「一切皆插件」,对话迁移这类能力同样以插件形式接入,而不是改动 DSH 本体。
这是什么¶
dsh-shuttle 仓库为 omdsh-dev/dsh-shuttle,包名 @deepseek-ai/dsh-shuttle,由 omdsh-dev 维护,采用 MIT 许可证,当前版本 0.1.0。它支持在 DSH 与 Codex、Claude Code、Pi、Reasonix、OpenCode 之间双向迁移对话记录,既可以作为插件在 DSH 内使用,也可以作为独立 CLI 离线运行。
迁移的工作方式¶
迁移前,每个来源会先投影为一个 provider-neutral 的中间模型,再转换成 DSH 事件或目标平台的原生导入格式。在目标支持的前提下,文本、推理内容、工具调用与结果、时间戳、工作目录以及 provider/model 身份都会保留。
并非所有数据都可移植:Provider 私有回放状态、缓存数据、UI-only 事件、token 分块与数据库索引不在迁移范围内。二进制/图片附件在无法安全复制字节时,会变成文本占位符。
安全设计¶
写入类操作有几条硬性约束:
- 默认 dry-run,带
--apply才真正执行写入; - 已存在的 DSH ID 与目标文件会被跳过,从不覆盖;
- 读取有大小/数量上限,且不递归符号链接目录;
- DSH 写入使用
ctx.sessionPersistence,JSONL 与 SQLite 后端均可工作; - OpenCode 通过官方 export/import JSON envelope 处理,从不直接编辑其数据库;
- Shuttle 从不删除源历史。
安装与启用¶
README 没有给出具体安装命令,只说明通过常规 DSH 插件工作流安装本包。安装后,捆绑的 cordis.patch.yml 会挂载 ctx.shuttle 与 migrate-conversations 技能,插件导出标准的 name、inject、Config、apply 符号。
运行环境为 Node ^22.19.0 || >=24.0.0,包管理器 pnpm@11.7.0。使用 CLI 前需要先构建:
pnpm install
pnpm build
构建后 CLI 入口为 lib/cli.js,package.json 中注册的 bin 命令名是 dsh-shuttle。
通过 Settings UI 迁移¶
打开 Settings → Conversation migration,可以看到两个独立的导入/导出单元,不需要手工拼命令:
- 在 Import to DSH 中选择来源平台,可选设置来源路径与数量上限;
- 在 Export from DSH 中选择目标平台、DSH 任务、目标路径与范围;
- 每个单元单独预览。Settings 预览使用专用 Remote API,不会创建 DSH 会话,也不会写目标文件;
- 查看该单元的报告,勾选确认后执行导入或导出。
执行按钮只在当前表单成功预览后可用;更改任何迁移输入都会使预览失效。
斜杠命令 /shuttle¶
在存在交互式 DSH 命令服务的环境中,可以在会话输入里输入 /shuttle 查看帮助并执行导入/导出,结果直接显示在 UI,不会发送给模型:
/shuttle import codex
/shuttle import codex --source "~/.codex/sessions" --apply
/shuttle export pi --destination "~/.pi/agent/sessions"
/shuttle export opencode --session <id> --destination /tmp/opencode --apply
不带 --apply 时都是预览。导出默认针对当前 UI 会话,可以通过重复 --session 或 --all 改变选择。
CLI 用法¶
CLI 提供 import/export 两个子命令,支持 --from/--to、--source、--destination、--session(可重复)、--all、--apply、--dsh-root。流程是先构建,再预览,确认报告后加 --apply 写入。
先看导入。默认 DSH 存储为 $DSH_HOME/sessions 或 ~/.dsh/sessions,可用 --dsh-root 覆盖:
node lib/cli.js import --from codex
node lib/cli.js import --from claude-code --source ~/.claude/projects
node lib/cli.js import --from pi --source ~/.pi/agent/sessions
node lib/cli.js import --from reasonix --source ~/.reasonix
检查 JSON 报告后,加 --apply 重复执行同一命令完成写入。
导出方向:
node lib/cli.js export --to codex --session <id> --destination ~/.codex/sessions --apply
node lib/cli.js export --to pi --destination ~/.pi/agent/sessions --apply
node lib/cli.js export --to reasonix --destination ~/.reasonix --apply
重复 --session 可选择多个会话;省略它则导出至配置的 maxSessions 上限。
OpenCode 的读写配合它自己的 export/import 命令完成:
opencode export <session-id> > /tmp/opencode-session.json
node lib/cli.js import --from opencode --source /tmp/opencode-session.json --apply
node lib/cli.js export --to opencode --session <dsh-session-id> \
--destination /tmp/dsh-opencode --apply
opencode import /tmp/dsh-opencode/<dsh-session-id>.opencode.json
Reasonix 方向,如果写入后它的目录里没有显示新的权威 JSONL 会话,运行一次 reasonix sessions reindex。
插件 API 与配置¶
插件暴露两个 API,同样遵循先预览、后写入的模式:
const preview = await ctx.shuttle.importConversations({
from: 'codex',
source: '/path/to/.codex/sessions',
})
await ctx.shuttle.importConversations({
from: 'codex',
source: '/path/to/.codex/sessions',
apply: true,
})
await ctx.shuttle.exportConversations({
to: 'claude-code',
sessionIds: ['session-id'],
destination: '/path/to/.claude/projects',
apply: true,
})
两个配置项控制读取上限:
| 配置项 | 默认值 | 含义 |
|---|---|---|
maxFileBytes |
64 MiB | 单个外部工件的最大尺寸 |
maxSessions |
500 | 每次操作的最大工件/会话数 |
适用场景与注意事项¶
它适合在多个编码智能体之间切换、想把历史会话集中到 DSH,或需要把 DSH 会话交给其他工具继续使用的开发者。使用前注意两点:
- Codex 与 Claude Code 不承诺稳定的公开磁盘转录 schema。读取器是宽容的,但这两家升级后需要重新预览;导出的 Codex/Claude JSONL 匹配当前观察到的 envelope,未来客户端可能需要显式导入器或适配器更新。
- 插件以当前 dsh 进程的权限运行,安装前应检查源码与许可证(MIT)。
结尾¶
经过上面的步骤,分散在各家工具里的对话记录就变成了可迁移的数据;默认预览、从不覆盖的设计让每次写入都可控。代码与文档见 GitHub 仓库: