DSH Shuttle
DSH Shuttle is a DeepSeek Harness plugin and offline CLI for bidirectional conversation migration between DSH and Codex, Claude Code, Pi, Reasonix, or OpenCode.
Every source is projected into a provider-neutral model before conversion to DSH events or the target's native import format. Text, reasoning, tool calls/results, timestamps, working directory, and provider/model identity are preserved where the target supports them.
Safety
- Operations are dry runs unless
--applyis present. - Existing DSH IDs and destination files are skipped, never overwritten.
- Reads are size/count bounded and do not recurse through symlink directories.
- DSH writes use
ctx.sessionPersistence, so JSONL and SQLite backends work. - OpenCode's database is never edited directly; Shuttle uses its official export/import JSON envelope.
Install
Install this package through the normal DSH plugin workflow. The bundled
cordis.patch.yml mounts ctx.shuttle and the migrate-conversations skill.
The plugin exports the standard name, inject, Config, and apply symbols.
DSH interface
Settings UI
Open Settings → Conversation migration to use two independent import and export units without composing a command manually:
- In Import to DSH, choose a source platform and optionally set a source path and limit.
- In Export from DSH, choose a target platform, DSH task, destination, and scope.
- Preview each unit independently. Settings previews use a dedicated Remote API and never create DSH conversations or write destination files.
- Review that unit's report, check its confirmation, and run the import or export.
The execution button is only available after a successful preview of the current form. Changing any migration input invalidates that preview.
Slash command
When the interactive DSH command service is present, type /shuttle in the
conversation input to see help. The command result is shown directly in the UI
and is not sent to the model.
/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
Import and export are previews unless --apply is supplied. Export defaults to
the current UI session; pass repeated --session flags or --all to change the
selection.
CLI
Build with pnpm build, then preview an import:
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
Review the JSON report and repeat with --apply. The default DSH store is
$DSH_HOME/sessions or ~/.dsh/sessions; override it with --dsh-root.
Export one or all DSH sessions:
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
Repeat --session to select multiple sessions. Omitting it exports up to the
configured maxSessions.
OpenCode
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
For Reasonix, run reasonix sessions reindex if its catalog does not show a
newly written authoritative JSONL session.
Plugin 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,
})
Configuration:
| Field | Default | Meaning |
|---|---|---|
maxFileBytes |
64 MiB | Maximum size of one external artifact |
maxSessions |
500 | Maximum artifacts/sessions per operation |
Limitations
- Codex and Claude Code do not promise a stable public on-disk transcript schema. Their readers are tolerant, but preview again after upgrades.
- Binary/image attachments become text placeholders when referenced bytes cannot be safely copied.
- Provider-private replay state, cache data, UI-only events, token chunks, and database indexes are not portable.
- Exported Codex/Claude JSONL matches currently observed envelopes; future clients may require an explicit importer or adapter update.
- Shuttle never deletes source history.
Development
pnpm install
pnpm typecheck
pnpm test
pnpm build
pnpm run validate:skill
No comments yet. Be the first to write one.