前言¶
如果你同時使用 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 倉庫: