dsh-session-importer
A dsh plugin that imports session records from other coding agents into the dsh session store, so they appear in the session list/search, render in the conversation UI, export, and resume like any native dsh session.
Supported sources
| Source | Location | Notes |
|---|---|---|
| Claude Code | ~/.claude/projects/<slug>/*.jsonl |
user/assistant messages, tool calls & results, thinking → reasoning blocks |
| Codex CLI | ~/.codex/sessions/**/*.jsonl, ~/.codex/archived_sessions/*.jsonl |
messages (output_text/input_text), function_call/local_shell_call/web_search_call + outputs, reasoning |
| Kimi Code CLI | ~/.kimi-code/sessions/*/agents/main/wire.jsonl |
prompts, assistant text + think → reasoning, tool calls/results; cwd from session_index.jsonl |
| Generic JSONL | any *.jsonl with role/content lines |
Gemini CLI, OpenCode, custom exports |
| Markdown transcript | any *.md with ## User / ## Assistant (or **User:** …) markers |
explicit --source markdown |
Unrecognized record types (attachments, hooks, summaries, snapshots) are skipped; tool results without a matching tool call are skipped and counted.
Installation
Install the package into a dsh profile and register the plugin row:
# 1. install into the web profile (from anywhere)
dsh plugin --profile web add file:/absolute/path/to/dsh-session-importer
# 2. append a patch row to ~/.dsh/profiles/web/cordis.patch.yml
- insert:
- id: session-importer
name: dsh-session-importer
Then restart dsh web (or dsh --profile headless if you also install it
there) to load the plugin.
After editing the plugin source, re-run the
dsh plugin --profile web addcommand — pnpm installs a snapshot copy into the profile, not a live link.
Usage
In the web UI command palette (or any command surface):
/import-sessions [<path>] [--source auto|claude|codex|jsonl|markdown] [--cwd <dir>] [--limit <n>] [--dry-run] [--retitle]
No
<path>— auto-discovers the known agent data directories listed above.<path>a file — imports that one transcript.<path>a directory — scans recursively for*.jsonl(*.mdonly with--source markdown).--source— force a parser; defaultautodetects per file.--cwd <dir>— override the recorded working directory of imported sessions.--limit <n>— cap messages per imported session (default unlimited).--dry-run— scan, parse, and report without writing anything.--retitle— backfill titles + sidebar projections for sessions imported by an older plugin version, without re-importing. Runs inside the host process (no restart needed). Run it once after upgrading the plugin:/import-sessions --retitle
Examples:
/import-sessions
/import-sessions ~/.claude/projects
/import-sessions /path/to/export.jsonl --source claude
/import-sessions /path/to/transcript.md --source markdown --cwd /path/to/project
/import-sessions --dry-run
Behavior notes
- Idempotent: each source file maps to a deterministic session id
(
import-<source>-<hash>, versioned — a parser fix bumps the hash input, so re-importing after an upgrade creates fresh sessions instead of being rejected as duplicates). Re-importing the same file unchanged is skipped as a duplicate, so running the command repeatedly is safe. - Durability: imports write directly through the dsh session-persistence backend (the same append-only, fsync-durable machinery the live agent path uses), so no live agent session is required and writes survive restarts.
- Fidelity: tool calls are kept as
tool-callcontent blocks plustool/call+tool/resultevents (paired by id), mirroring native dsh sessions; Claude Codethinkingblocks and Codexreasoningblocks are imported asreasoningcontent blocks so tool-heavy turns still show the model's reasoning; very long blocks are truncated (200 KB text / 100 KB tool results) to keep imports bounded.
Development
node test/harness.mjs # boots an in-process cordis context + jsonl persistence
# against a temp root, imports the fixtures, and
# verifies the resulting logs reload cleanly
Requires the @deepseek-ai/* packages resolvable from the plugin directory
(they are when the plugin is installed into a dsh profile).
No comments yet. Be the first to write one.