# dsh-chat-import

> Import conversation history from 15 external AI coding agents (Claude Code, Codex, ChatGPT, Cursor, opencode, etc.) as fully resumable

## Metadata

- Author: [@Nwflower](https://github.com/Nwflower)
- Repo: <https://github.com/Nwflower/dsh-chat-import.git>
- GitHub: [Nwflower/dsh-chat-import](https://github.com/Nwflower/dsh-chat-import)
- Stars: 85
- Language: JavaScript
- License: [MIT](https://spdx.org/licenses/MIT.html)
- Homepage: <https://www.npmjs.com/package/dsh-chat-import>
- Topics: `agent`, `ai-agents`, `automation`, `chatgpt`, `claude-code`, `codex`, `cursor`, `deepseek`, `deepseek-harness`, `developer-tools`, `dsh`, `dsh-plugin`, `gemini`, `import`, `jsonl`, `migration`, `openai`, `plugin`, `sessions`, `transcript`
- Forks: 13
- Open Issues: 1
- Last push: 2026-08-20T07:41:02.000Z
- Added: 2026-08-13T00:00:00.000Z

## Install

```bash
dsh plugin --profile web add github:Nwflower/dsh-chat-import
```

## Wiki

## One-Line Description
Import conversation history from 15 external AI coding agents including Claude Code, Codex, ChatGPT, Cursor, opencode, ZCode, Grok Build, Hermes (and any local JSONL) with full fidelity into resumable DSH sessions, while supporting reverse export to Claude Code/Codex/Kimi and cross-machine portable backups.

## Core Capabilities
- Import local history from 15 sources: Claude Code / Codex / ChatGPT CLI / ChatGPT web export / Cursor / Gemini CLI / Reasonix / opencode / ZCode / Grok Build / OpenClaw / Pi Coding Agent / Hermes / Kimi CLI & Code / Qoder CLI, plus DSH session logs and arbitrary local JSONL
- Preserve tool calls and results, thinking blocks, titles, models, and timestamps; ChatGPT exports support branch restoration; opencode/zcode/pi respect source-side compressed summaries with optional full import
- Idempotent and incremental: skip if source file unchanged, append only new rounds when growing, actively report when shrinking; `force:true` saves a complete copy with new id
- Reverse matrix: DSH sessions can export to Claude Code JSONL, Codex rollout, Kimi wire, and portable exchange packages with SHA-256 dual fingerprints
- Reverse sync: `sync_to_claude` incrementally writes DSH new rounds back to Claude Code JSONL, with overwrite protection guards, never silently overwrites
- Browser sidebar: "Import Sessions" button + workspace-grouped browsing panel + single/multi-select import, shared read-only discovery cache
- Companion tools: import agent/skill configurations, generate MCP mirror snippets, configuration migration suggestions, `verify_session` structure validation, `doctor` health check, `sync_to_claude` / `export_bundle` / `restore_bundle`

## Technical Implementation
- **Language**: JavaScript ESM (pure ESM, zero build, source is the release artifact)
- **Key Dependencies**: `@deepseek-ai/cordis` (DSH plugin framework), `@deepseek-ai/dsh-tools` (DSH tool registration API), `@deepseek-ai/dsh-client-locale` (sidebar i18n), `fzstd` (DSH session log .zstd decompression)
- **Architecture Pattern**: Native Cordis plugin, registers 22 DSH tools via `apply(ctx)` with delayed browser panel route mounting (`ctx.inject(['webServer'])`); `lib/convert/*` and `lib/export/*` maintain zero DSH dependency pure functions for isolated unit testing; `lib/*.mjs` (host-facing, consumes ctx) handles orchestration and persistence
- **Entry Files**: `index.mjs` (thin composition layer) + `lib/tools.mjs` (22 tool registrations) + `cordis.patch.yml` (profile bundle insert)

## Use Cases
- Already accumulated extensive context in Claude Code / Codex / Cursor and want to seamlessly continue in DSH instead of starting from scratch
- Want to migrate sessions across AI coding tools (Claude ↔ DSH ↔ Codex ↔ Kimi) for backup or multi-platform comparison
- Need to carry sessions along during multi-machine migration without corrupting source files or losing workspace grouping
- Want to consolidate external agent custom prompts, skills, and configurations into DSH's skills directory

## Prerequisites & Compatibility
| Dependency | Minimum Version | Description |
|---|---|---|
| DeepSeek Harness (dsh-tools) | 0.1.0-rc.6+ | peer `@deepseek-ai/dsh-tools ^0.1.0-rc.6`, tested against dsh 0.1.0-rc.6 |
| @deepseek-ai/cordis | ^4.0.1 | peer dependency, DSH plugin framework |
| @deepseek-ai/dsh-client-locale | >=0.1.0-rc.6 | peer dependency, sidebar panel i18n |
| react | >=18.0.0 | peer dependency, sidebar bundle rendering |
| Node.js | >=22.13 | engines.node, first version with built-in `node:sqlite` |
| Platform | Cross-platform | macOS / Windows / Linux all work; opencode / zcode / hermes three SQLite sources depend on `node:sqlite`, CI tests on Linux pass |

## Installation
```bash
dsh plugin --profile web add github:Nwflower/dsh-chat-import
```

## Configuration
This plugin requires no pre-declared configuration in profile; behavior is controlled via call parameters and environment variables. The following table describes common parameters for tool calls and environment variables.

| Config | Type | Description | Default |
|---|---|---|---|
| `path` | string | Source file or directory path (single file or directory batch) | Required |
| `force` | boolean | When true, saves a complete copy with new id even if already imported | false |
| `budget` | integer | Context budget (token count); priority: this param > `DSH_IMPORT_CONTEXT_BUDGET` > dynamic model window > 550k | unset |
| `preview` / `dryRun` | boolean | When true, parses only without writing to disk, zero side effects | false |
| `sessionId` | string | Override target DSH session id (single file mode) | `import-<source-id>` |
| `recursive` | boolean | Whether directory mode recursively scans subdirectories | true |
| `expectedHash` | string | Expected SHA-256 (lowercase hex) of source file; rejects write if mismatch | unset |
| `restamp` | boolean | When true, shifts session timestamps to current time (preserving relative intervals) | false |
| `workspaceMode` | string | `auto`/`per-project` groups by cwd or source directory; `dedicated` attaches all to same workspace | auto |
| `workspaceDir` | string | Workspace directory when `workspaceMode=dedicated` | `$DSH_HOME/dsh-chat-import-workspace` |
| `DSH_IMPORT_CONTEXT_BUDGET` | env | Context budget token count (whole library import budget chain) | unset |
| `DSH_IMPORT_SESSION_HINT` | env | `=0` disables migration hints on new session start | on |
| `DSH_IMPORT_CONTEXT_BRIDGE` | env | `=1` bridges Claude memory/CLAUDE.md/skills to current agent | off |

> Sidebar panel routes and command surface (`/import`, `/resume-claude`, etc.) automatically enable under web/profile combination; headless profiles or profiles without webServer service won't mount panel routes, but the 16 import tools remain fully usable.

## FAQ
**Q: Do I need to configure anything after installation to use it?**

A: Just restart dsh after installing; the plugin consumes host public services by default. If the corresponding agent's local data directory is not installed on the machine, import tools will error directly on missing paths, won't auto-create.

**Q: Will it rewrite my original Claude Code / Codex history files?**

A: No. Source transcripts and SQLite databases remain read-only throughout; import results only append new events to DSH session directory, import metadata writes to `$DSH_HOME/dsh-chat-import/imports.json`. `sync_to_claude` appends writes back to Claude Code files, but with overwrite protection (skips and reports if source shrinks or externally modified), `force:true` re-anchors.

**Q: Will re-importing the same history create duplicate sessions?**

A: No. Source files with unchanged mtime/size are idempotently skipped, won't re-read source data; growing source files append only new rounds to the same session; shrinking source files are detected and reported. `force:true` skips idempotency checks and saves a complete copy with new id.

**Q: Can imported sessions continue chatting, is the tool panel normal?**

A: Yes. Import尽量走 host 的 `agents.create` 路径并挂载默认 preset scope 和默认模型,工具面与原生 DSH 会话一致,刷新会话列表即可接着聊;若 `agents` 服务不可用则自动回退到 `sessionPersistence`,不会因此中断。

**Q: I have hundreds of histories, how to import all at once?**

A: Click "Import Sessions" in browser sidebar to open panel, browse by workspace grouping + multi-select import; or run `scan_discover()` directly in DSH session to see the list, then call `import_<source>({ path: "<data root>" })` sequentially. Directory paths recursively scan, each transcript becomes a separate session.

**Q: How to undo an imported session?**

A: Use `retract_import({ sessionId })` (or `sourcePath`), the plugin only removes registry records and returns guidance for manually deleting artifacts, never calls any deletion. After manually deleting artifacts per guidance, `force:true` re-import to get a fresh session.

**Q: Can I continue chatting imported sessions on another machine?**

A: Yes. Use `export_bundle({ sessionId })` to export `.dshbundle.json` (with SHA-256 dual fingerprints + cross-machine placement info), copy to another machine and run `restore_bundle({ path })`; when original `cwd` is unreachable on new machine, falls back to bundle file's directory and reports `cwdAvailable:false` in result, won't silently group to "ungrouped".

**Q: What to do when receiving "TOOL_RUNTIME_SCHEDULER missing" error?**

A: This is the plugin actively throwing error when host's `@deepseek-ai/dsh-tools` version is below 0.1.0-rc.6 (prevents polluting session history with old ABI tool registrations). Upgrade the host.

## Getting Started Difficulty
Beginner — install plugin and restart DSH, import single file with default parameters; sidebar browsing + multi-select import requires no code. Complex scenarios (budget trimming, cross-machine migration, dedicated workspace) involve 1-2 extra parameters, README is enough to get started.

## Known Issues & Limitations
- `node:sqlite` first available version is Node 22.13; Windows / Linux / macOS all work, but host environment must satisfy `>=22.13`
- `import_dsh` and `export_bundle` share the same converters, but DSH's own history doesn't enter `scan_discover`'s 15-source auto-roots by default (requires explicit path or format)
- Kimi subagent sessions recorded as `SubagentEvent` in parent wire are skipped; needs separate import of subagent directory or new layout `agents/<agentId>/wire.jsonl`
- Cursor agent transcript doesn't include `tool_result`, only imports `tool_use` call history
- `sync_to_claude` defaults to strict guards (source shrink / external modification / tail mismatch / concurrent writer all skip and report); `force:true` re-anchors watermark and chain tail, may overwrite external modifications
- Browser panel routes depend on host's `webServer` service mounting late; headless profiles or profiles without webServer service don't mount panel but import tools remain usable

---

This document is auto-generated by [deepseek-plugin.org](https://deepseek-plugin.org). HTML page: [dsh-chat-import](https://deepseek-plugin.org/plugins/Nwflower/dsh-chat-import)
Wiki generated by AI (model: `MiniMax-M2.7`)
