Back to home@birdmanhj

dsh-mv-session

A plug-in for Deepseek Harness that easy to move/rename session from old workspace to new workspace.

Stars
0
Language
JavaScript
Created
Aug 25, 2026
Updated
Aug 25, 2026
GitHub repo

Introduction

dsh-mv-session

English | 中文

GitHub tag npm License: MIT topic: dsh-plugin

A DeepSeek Harness (DSH) plugin that migrates sessions/workspaces to a new path and/or title — one tool call, one restart, one verify command.

install → ask the agent to "migrate workspace X to Y" → restart dsh web (the only restart)
        → delete transition symlinks → verify (read-only) → done

Pain point

After renaming or moving a workspace directory, DSH does not migrate its sessions: old sessions stay bound to the old path (tool cwd breaks with ENOENT), DSH auto-creates an empty workspace plus empty sessions at the new path, and the four persisted layers (session header cwd, sessions directory, workspace registry, projection cache) disagree. This plugin performs the whole migration in one step, with backups, and tells you exactly which manual steps remain.

Frame-safe by design

session.jsonl.zstd is a multi-frame Zstandard stream; at boot, DSH asserts that frame 0 decompresses to exactly one header line (assertZstdHeaderFrame). A whole-log "decompress → edit → recompress" round-trip collapses everything into one frame and makes dsh web crash at boot with "first frame is not exactly one header line" (hit in production on 2026-08-24). The bundled CLI rewrites only frame 0, leaves every other frame byte-identical, repairs previously collapsed logs (one checksummed frame per line), and re-verifies the boot invariant before atomically replacing the file.

Install

dsh plugin --profile web add dsh-mv-session          # from npm
dsh plugin --profile web add /path/to/packages/dsh-mv-session   # from a checkout
# restart dsh web once to load the plugin

Usage — plugin tool (recommended)

In any DSH session, just say: "migrate workspace /path/old to /path/new, title New Name". The agent runs dry_run first so you can review the plan, then executes for real.

Parameters: from / session (one of), to (required), title, dry_run, mkdir, merge_dir, backup_dir, cleanup_empty, verify (read-only closing check).

Usage — CLI

node migrate_session.cjs --from /old --to /new --title "New" --mkdir --dry-run  # 1 preview
node migrate_session.cjs --from /old --to /new --title "New" --mkdir --yes      # 2 migrate (auto-backup)
# 3 restart dsh web (the only required restart) → confirm in the GUI
# 4 delete the transition symlinks (paths are printed in the report)
node migrate_session.cjs --verify --from /new                                   # 5 read-only check, done

Why exactly one restart (and not two, not zero)

The migration edits disk, but the running dsh web holds a full in-memory state (session header cwd, log append path map, workspace registry) that never re-reads disk before restart — worse, it checkpoints its stale in-memory values back over workspace.json and the projection cache. One restart rebuilds everything from disk. The transition symlinks exist only to keep the old process alive during that window; once restarted, nothing references the old paths, so they can be deleted safely.

A second restart is not required: the post-symlink confirmation is replaced by the read-only --verify check (registry record ↔ session header cwd ↔ frame invariant ↔ directories ↔ cache). Zero restarts is impossible today: DSH exposes no online "rehome" API — a process restart is the only supported way to refresh the in-memory layer.

Parameters

ParameterTypeRequiredMeaning
fromstringone ofCurrent workspace path (may be a symlink)
sessionstringone ofSession id; the workspace is located automatically
tostringyesTarget workspace path
titlestringNew title (default: basename of to)
dry_runboolPrint the plan without changing anything
mkdirboolAllow creating the target directory
merge_dirboolMerge into an existing non-empty target (refused by default)
backup_dirstringBackup location (default <dsh-home>/migration-backups/)
cleanup_emptyboolRemove auto-created empty sessions at the target (default true)
verifyboolRead-only consistency check that replaces the second restart

Safety & rollback

  • Preflight validation before the first mutation: an unreadable log aborts with nothing modified.
  • Same-directory guard, atomic tmp+rename writes, full backups before every run.
  • Rollback = restore the backup directory + run the migration in reverse (new path → old path).

Documentation

Development

node --check lib/migrate_session.js
node tests/migrate_e2e_scratch.js --boot <real-session-log>   # frame invariant + real dsh web boot
node tests/migrate_edge_cases.js                              # merge/symlink/no-zstd/guards/preflight

The npm package lives in packages/dsh-mv-session/; lib/migrate_session.cjs there is synced from the root lib/migrate_session.js (the package is ESM while the CLI runs as a CommonJS child process).

License

MIT