Claude Code /rewind for DeepSeek Harness: git-first workspace snapshots before every mutating tool execution, turn-boundary session forks, and a one-shot /rewind command that restores files and forks the session back to a checkpoint.
Install
# from npm (prebuilt)
dsh plugin --profile web add dsh-checkpoint-rewind
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:PerryLink/dsh-checkpoint-rewind
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).
README
dsh-checkpoint-rewind
Turn “back to step N” into one command — three-state workspace, config, and session checkpoints, rolled back in one approved transaction.
A rewind capability-seam plugin for DeepSeek Harness: capture the workspace with side-effect-free git primitives before every mutation, then guard, restore files, restore config, and fork the session — the original session history is never truncated.
Install · Configuration · FAQ · 简体中文 · English · Español · Português · हिन्दी
dsh plugin --profile <name> add dsh-checkpoint-rewind
Community plugin, not affiliated with DeepSeek. Canonical repository: https://github.com/PerryLink/dsh-checkpoint-rewind (Gitee is a mirror).
What it is
dsh-checkpoint-rewind captures a three-state unified checkpoint — workspace, session cursor, and plugin config — and restores one or all three with a single approved command. Workspace snapshots prefer side-effect-free git primitives (stash create / commit-tree); non-git directories (and repos with an unborn HEAD) degrade to incremental copy snapshots with hardlink reuse. Session rollback never truncates the original session: it forks a new child session at the checkpoint boundary, leaving the original history intact. Checkpoints are captured before mutating tools, on an automatic interval, manually via /checkpoint, and as a guard before every rewind; the Settings page adds a checkpoint timeline with pairwise line-level diffs.
Three-step setup
Install (pick one channel):
# git channel (latest main; equivalent to git+https://github.com/PerryLink/dsh-checkpoint-rewind.git) dsh plugin --profile web add github:PerryLink/dsh-checkpoint-rewind # npm channel (published releases) dsh plugin --profile web add dsh-checkpoint-rewind # tarball channel: npm pack in this repo, then dsh plugin --profile web add ./dsh-checkpoint-rewind-<version>.tgzPure ESM, no build step —
index.mjsandlib/are the shipped artifacts.Minimal config: compose the storage stack (required for checkpoint persistence) and mount the plugin row. Without the storage stack the plugin still mounts and never blocks profile startup; checkpoint/rewind commands return a structured error naming the exact rows to add:
- insert: - id: checkpoint-rewind-storage name: '@deepseek-ai/dsh-storage' - id: checkpoint-rewind-storage-json name: '@deepseek-ai/dsh-storage-json' config: root: !!js dshHomePath('checkpoint-rewind/storage') - id: checkpoint-rewind-storage-domain name: '@deepseek-ai/dsh-storage-domain' config: backend: json - id: checkpoint-rewind name: dsh-checkpoint-rewind config: provider: auto confirmVia: autoVerify it mounts:
dsh --profile web --dump-config | grep -A4 'id: checkpoint-rewind'Then list checkpoints; workspace mutations create them automatically:
> /rewind list brief rewind: 3 checkpoints (newest last): #a1b2c3d4 · (git) · turn 2 step 1 · 2026-08-14 12:00:01 (3 min ago) · trigger: bash · 4 files · 1.2 MiB #b2c3d4e5 · (git) · turn 2 step 3 · 2026-08-14 12:00:41 · trigger: str_replace_editor · 2 files · 310 KiB #c3d4e5f6 · (copy) · turn 3 step 1 · 2026-08-14 12:01:10 · trigger: write · 1 file · 90 KiB run "/rewind <id>" to restore files and fork the session from that checkpoint
Uninstall: dsh plugin --profile web remove dsh-checkpoint-rewind — snapshot files stay until you delete $DSH_HOME/dsh-checkpoint-rewind; git objects are garbage-collected.
Checkpoints persist through the
storageDomainservice. Profiles that already compose the stack work out of the box; a bare profile still mounts and can capture manually, but commands fail loudly when the domain cannot open — they never silently degrade to “no checkpoints”.
Core capabilities
dsh-checkpoint-rewind leaves a restorable three-state record before every mutation and turns restore into a fixed-order transaction:
- Three-state record — every checkpoint stores the workspace state (git tree SHA, or a copy manifest), the session event cursor (
seq+ turn boundary), and a config snapshot, tagged by source (manual/auto/guard/mutation). - Four capture triggers — before every mutating tool (
fs/write-intent,fs/edit-intent,tools/pre-execute), on automatic interval (autoCheckpoint, default every step), manually (/checkpointand thecheckpointtool), and as a guard before every rewind. - git-first provider —
git stash create/commit-treeproduce unreferenced snapshot objects that never touch your worktree, index, or history; restore is worktree-only and path-explicit. Non-git directories (and unborn-HEAD repos) degrade to an incrementalcopyprovider with hardlink reuse. - One-shot rollback —
/rewind workspace|session|config|all <target>restores the selected states;previewis a read-only impact report,diff <a> <b>compares two checkpoints,cleardeletes them (this session;clear --allspans all sessions and workspaces). - Fork-based session rollback — session rollback replays events up to the checkpoint boundary through the official
SessionStore.forkprimitive into a new child session (falling back to the seededsessions.createpath when the host has no fork or the checkpoint has no boundary); the original session keeps its full history. - Settings page timeline — the
Plugins → Checkpointstab renders the session's checkpoints with pairwise line-level diffs (diffRenderer) and per-file selective restore (selectiveRestore).
Commands & tools surface
| Surface | Kind | Notes |
|---|---|---|
/rewind |
command | [workspace|session|config|all] <number|id-prefix|step <N>|latest> · list [brief] · diff <a> <b> · preview <target> · clear [--all] |
/checkpoint |
command | [note <text>|list|diff <a> <b>] — capture a manual checkpoint |
checkpoint |
tool | Capture a manual checkpoint with an optional note |
fs/write-intent · fs/edit-intent · tools/pre-execute |
listeners | Pre-mutation capture (prepend pass-through; never steals the policy slot) |
session/event |
listener | Turn/step tracking, auto interval, boundary backfill, turn-end pruning |
checkpoints projection |
session projection | Timeline strip folded from the session log |
| Settings page timeline | client | Plugins → Checkpoints tab with pairwise diffs and per-file selective restore |
Examples
These are the plugin's real entry points; install once, then call one.
Detailed example — command /rewind preview cp-9, output:
rewind preview: checkpoint #cp-9 (provider git, turn 2 step 3)
restoring it would overwrite 2 file(s):
a.txt
b.txt
5 file(s) already match the checkpoint (not touched).
no files are deleted: 1 file(s) created after the checkpoint would be left in place:
new.txt
run "/rewind <id>" to confirm and apply (a guard checkpoint is captured first)
Observed from test/checkpoints.test.mjs:289-301; lib/checkpoints.mjs:484-500
Failure branch — input /rewind nope, output:
rewind: unknown checkpoint id "nope" (run /rewind to list)
Observed from plugins/dsh-checkpoint-rewind/lib/errors.mjs:72; plugins/dsh-checkpoint-rewind/index.mjs:1223; plugins/dsh-checkpoint-rewind/test/index.test.mjs:346-350
Brief examples: /checkpoint · /rewind preview
Session numbers
- Every checkpoint gets a number when it is created, starting at
1./rewind 3resolves that number exactly — digits are never treated as an id prefix, so/rewind 3can never land on the checkpoint whose UUID happens to start with3. - Scope: per session (
sessionId). Each session numbers its own checkpoints; a number is unique inside its session, and/rewind <number>resolves against the checkpoints of the current session (and workspace) only. - Monotonic and never reused. Quota pruning (
maxSnapshots) and/rewind clear//rewind clear --alldelete records but never free a number: after a clear the next checkpoint continues from the previous high-water mark (so after#1 #2 #3and aclear, the next one is#4, not#1). The number is stored on the record itself and the counter lives in the domain's global slot, so deleting records cannot reset it. - Older checkpoints are numbered on first sight. Records written before this feature (no number field) are numbered in creation order the first time the session is listed or rewound, and that numbering is persisted; brand-new checkpoints continue after it. Nothing is skipped or reassigned, and id-prefix addressing keeps working for them.
/rewind list(the detailed list) is unchanged: it still prints the 8-char id per line and its last line points at/rewind list brieffor the numbers.
preview resolves through the same addressing and prints the impact without asking for confirmation or writing anything. --files restores only the named files through the same approval-gated transaction (unknown paths fail closed; it is incompatible with workspaceRestore: reset-hard and disabled when selectiveRestore: false).
Why another rewind plugin?
| Plugin | What it sells | Restores files? | Rewinds the session? |
|---|---|---|---|
| dsh-checkpoint-rewind (this) | git-object snapshots + three-state rollback + one-shot restore | ✅ full workspace state | ✅ seed-replay child session |
| Anionex/dsh-turn-rewind | persistent Change Ledger of per-mutation deltas | ✅ by replaying inverse deltas | ✅ its own ledger model |
| LingLambda/dsh-undo | pure context rollback to the last completed step | ❌ | ✅ context only |
| Mongfayi/dsh-recall | message recall (remove a turn and everything after) | ❌ (explicitly) | ✅ turn removal |
The difference in one sentence: dsh-checkpoint-rewind captures the workspace state with side-effect-free git primitives before each mutation, and makes “back to step N” one approved command — guard checkpoint first, files restored second, config restored third, session replayed fourth, each phase logged. No delta bookkeeping to drift, no message-level editing (that belongs to a different plugin), no cross-device sync.
How it works
capture ── fs/write-intent · fs/edit-intent · tools/pre-execute (prepend, pass-through)
── step/start auto interval ── /checkpoint · checkpoint tool ── pre-rewind guard
│
▼ ProviderRegistry.resolve(auto) → git: stash create / commit-tree
│ copy: incremental dir + hardlinks
▼
checkpoints storage domain (SQLite rows / JSON file) + checkpoint/* event (adaptive gate)
/rewind <target> ── confirm (userQuestions / approval, fail-closed) ──▶ guard checkpoint
├─ workspace: provider.restore(ref) (restore | reset-hard)
├─ config: settings write-back (persisted on the profile patch)
└─ session: SessionStore.fork(source, boundary) → new child session (original untouched)
Full decision record, event vocabulary, and the provider seam contract: ARCHITECTURE.md.
Session events (rc.2 note)
The plugin declares checkpoint/snapshot, checkpoint/bound, checkpoint/prune, and checkpoint/rewind as log-only SessionEventMap members. Harness rc.2 has no plugin event-registration surface and Session.append does not stamp the ignorable envelope (its third argument is surface intent, not options), so appending unknown types would make the session unreadable on reload. The plugin therefore appends through an adaptive gate: a runtime probe (on a detached, never-persisted session store) detects whether the host's append stamps the ignorable envelope — on rc.2 the gate stays closed; on hosts that support it, checkpoint/* events are appended with ignorable: true automatically. Until then the authoritative audit chain is command/run + command/done (harness-known) plus the durable checkpoints storage domain.
Web UI anchor
The plugin returns the new session id in the command result (session: <id>) and the Web shell can navigate there. The session-projection unit checkpoints is shipped: whenever ctx.sessionProjections exists, the plugin registers the unit via ctx.inject (folds checkpoint/snapshot|bound|prune|rewind into a whole-value list) — it stays an empty list on rc.2 hosts until a harness build ships the checkpoint/* vocabulary or the ignorable envelope, then fills in with zero plugin changes.
Integration verification
A real assembled-headless integration run (npm run test:integration) drives the full flow: the agent modifies files across two turns, then /rewind preview inspects the impact read-only (no confirmation gate, no writes) and /rewind <id> restores the files and replays the session into a new child session. The run asserts the file contents, the replayed child context, the guard checkpoint, and that files created after the checkpoint survive — for both the copy and git provider flows (the git flow also asserts HEAD and the reflog are untouched). The driver lives in test/integration/rewind-headless.mjs.
Configuration
All tunables are Schemastery Config fields (changeable from cordis.yml); nothing is hardcoded. Provider options (gitBin, snapshotDir, excludeGlobs, verifyByHash) are read from the live config at use time, so cordis.yml changes apply without a restart. An id-targeted override replaces the whole row — restate every key you need.
Most-used keys:
| Key | Default | Meaning |
|---|---|---|
enabled |
true |
Master switch; false removes the commands, listeners, and providers entirely |
provider |
auto |
Snapshot provider: auto (git if available, else copy) · git · copy |
maxSnapshots |
50 |
Checkpoints kept per session (oldest pruned first) |
maxSnapshotBytes |
536870912 (512 MiB) |
Global incremental-byte soft quota (newest per live session always retained) |
confirmVia |
auto |
Confirmation channel: auto (userQuestions first) · userQuestions · approval |
preRewindCheckpoint |
warn |
Guard checkpoint before restore: warn · require · off |
workspaceRestore |
restore |
Workspace rollback: restore (safe overwrite) · reset-hard (CC-style, opt-in) |
autoCheckpoint.enabled |
true |
Automatic interval snapshots on step/start |
| Key | Default | Meaning |
|---|---|---|
enabled |
true |
Master switch; false removes the commands, listeners, and providers entirely |
provider |
auto |
Snapshot provider: auto (git if available, else copy) · git · copy |
gitBin |
git |
Git executable path |
snapshotDir |
$DSH_HOME/dsh-checkpoint-rewind (fallback ~/.dsh/dsh-checkpoint-rewind when $DSH_HOME is unset) |
Root for copy-provider snapshots |
maxSnapshots |
50 |
Checkpoints kept per session (oldest pruned first) |
maxSnapshotBytes |
536870912 (512 MiB) |
Global incremental-byte soft quota (newest per live session always retained) |
pruneOnTurnEnd |
true |
Run quota pruning when a turn ends |
mutationTools |
['bash','write','edit','str_replace_editor','pwsh','terminal_send'] |
Tools treated as mutating at tools/pre-execute |
excludeGlobs |
['node_modules','.git','.dsh','dist','build'] |
Glob patterns skipped by the copy provider |
confirmVia |
auto |
Confirmation channel: auto (userQuestions first) · userQuestions · approval |
listLimit |
10 |
Checkpoints shown by bare /rewind |
preRewindCheckpoint |
warn |
Guard checkpoint before restore: warn · require · off |
verifyByHash |
false |
Copy-provider content-hash comparison and restore verification |
autoCheckpoint.enabled |
true |
Automatic interval snapshots on step/start |
autoCheckpoint.intervalMinutes |
0 |
Interval; 0 = every step |
workspaceRestore |
restore |
Workspace rollback: restore (safe overwrite) · reset-hard (CC-style, opt-in) |
diffRenderer |
pairwise |
Settings-page diff renderer: pairwise (line-level text) · side-by-side (per-file two-column) |
selectiveRestore |
true |
Per-file selective restore (/rewind … --files) and the panel's per-file checkbox + size total |
promptSection |
true |
Inject a short role-statement prompt section |
checkpointTool |
true |
Register the checkpoint model tool |
Example override in your profile patch:
- insert:
- id: checkpoint-rewind
name: dsh-checkpoint-rewind
config:
provider: auto
maxSnapshots: 50
maxSnapshotBytes: 536870912
pruneOnTurnEnd: true
confirmVia: auto
preRewindCheckpoint: warn
FAQ
No — it uses git where available. In a git repo you get byte-perfect, deduplicated snapshot objects without touching history; in any other directory the copy provider does the same with plain files. Regular commits remain your long-term history.
Because destroying state is not the job of a safety net. The plugin only creates unreferenced objects and performs worktree-only, path-explicit restores by default, so a bad rewind can never lose history, the index, or files created after the checkpoint. reset-hard is available behind workspaceRestore: 'reset-hard' for users who explicitly want CC parity.
No ref is held on git-provider snapshots. They're unreferenced stash create/commit-tree objects by design, and discard deletes only the record, leaving the object itself for git gc. Two independent things bound how long a checkpoint actually stays restorable: the plugin's own quota pruning (maxSnapshots, default 50 kept per session; maxSnapshotBytes, a default 512 MiB global soft quota enforced via pruneAll() on capture and swept on turn ends), and the host repo's git gc. With git's defaults, unreferenced objects survive until an auto-gc runs, and even then only objects older than gc.pruneExpire (2 weeks by default) get pruned. A manual git gc --prune=now, an aggressive repack, filter-repo, or a fresh clone can drop them immediately. Pruned objects are now detected up front: the git provider probes the snapshot object before restore (git cat-file -e) and fails loudly when it is missing instead of silently restoring nothing, and a doctor pass walks every checkpoint record to probe object existence and badge unrestorable ones ([UNRESTORABLE: object missing] in the list). The doctor pass is implemented and tested but not yet wired into the restore path (restore does not yet consult the unrestorable marking; tracked in discussion #13).
File restoration is step-precise (/rewind step <N> = nearest snapshot ≤ N). The session replay, however, respects the harness's replay granularity: the child session is seeded up to the checkpoint's turn boundary.
Nothing is touched — the plugin fails closed (unavailable/rejected), keeps the checkpoint, and returns an explanatory error. With confirmVia: approval on rc.2 the message says to mount userQuestions, because approval requires an open turn and commands run between turns.
Yes — every approved rewind captures a guard checkpoint of the pre-rewind state first; the result prints rewind guard: <id>, and /rewind <guard-id> restores that state.
The session number (/rewind 3 — see /rewind list brief; per session, monotonic, never reused), the unique id prefix (the 8-char short id in the list still works), /rewind step <N>, and /rewind latest. /rewind clear deletes this session's checkpoints, and /rewind clear --all deletes checkpoints across all sessions and workspaces (files untouched) — neither one resets the numbering. /rewind preview <target> uses the same addressing to show the impact without changing anything.
Because a number is an address, not a position: reusing #1 for a different checkpoint after a clear would silently repoint anything that mentioned #1. The counter is persisted in the checkpoints domain (global slot) and each record stores its own number, so pruning and clearing delete snapshots without recycling ids.
It resolves the checkpoint, then runs a read-only comparison: which files would be overwritten (or recreated), which already match, and which files created after the checkpoint would be left in place. It never prompts, never writes, never forks, and records no checkpoint/rewind event — the approval gate only runs on a real /rewind <id>.
Troubleshooting
| Symptom | Cause / fix |
|---|---|
/rewind <id> says rewind cancelled: no confirmation answerer |
No userQuestions/approval channel is mounted — the plugin fails closed. Run in the Web UI (or mount a question provider); confirmVia selects the channel. |
/rewind <id> says approval requires an open turn … |
Commands run between turns and approval needs a turn — mount userQuestions or set confirmVia: userQuestions. |
rewind: checkpoint registry unavailable |
The checkpoints storage domain could not open. Either the storageDomain service is not composed (add the storage stack rows from Three-step setup: @deepseek-ai/dsh-storage + @deepseek-ai/dsh-storage-json with config root + @deepseek-ai/dsh-storage-domain with config backend: json) or the backend is erroring; check the harness logs. |
A checkpoint lists as fork: pending (turn not closed) |
Its turn has no turn/end yet; files can still be restored, but the session replay waits for the turn to close. |
files restored … but the session was NOT replayed |
The transaction's session phase failed (no closed boundary, or replay rejected). Files stay restored; use the printed rewind guard: <id> to undo. |
rewind: aborted — the pre-rewind guard checkpoint could not be captured |
preRewindCheckpoint: require refused the rewind because the guard capture failed; fix the storage (or set warn/off). |
A checkpoint lists as (copy) even though the directory is a repo |
Unborn HEAD (no initial commit): git snapshot primitives require HEAD, so the plugin degrades to copy until the first commit. |
MISSING_CREDENTIAL in headless runs |
Unrelated to this plugin: no DEEPSEEK_API_KEY is configured for the model provider. |
| Snapshot storage grows | Pruning runs after every snapshot and at turn/end (pruneOnTurnEnd); lower maxSnapshots / maxSnapshotBytes, run /rewind clear, or delete $DSH_HOME/dsh-checkpoint-rewind after uninstalling. |
Security boundaries
- Git history is untouchable. The git provider runs only whitelisted side-effect-free primitives —
stash create,commit-tree,restore --worktree,ls-tree,diff-tree,ls-files,status,rev-parse,cat-file -e— enforced by a runtime assertion, and object refs are validated as hex ids before being passed to git (a tampered record cannot inject git options). Noreset --hardby default, noclean, no index/history mutation, ever (seeworkspaceRestorebelow). - Overwrite rollback, never deletion. Restore only overwrites captured files, and the git provider restores explicit paths (
git restore … -- .would delete filesgit add-ed after the checkpoint). Files created after the checkpoint (untracked or staged) are reported and left in place. - No writes through links, no path traversal. The copy provider validates checkpoint refs before joining them into snapshot-directory paths, and refuses to restore through a destination (or ancestor) that has become a symbolic link — so a restore can never follow a link out of the workspace.
- Restore requires approval. Overwriting user files always goes through the confirmation seam with
asksemantics; a missing, throwing, or answering-no answerer fails closed./rewind previewis the read-only way to inspect the impact first. - Rewind is reversible. Before restoring, a guard checkpoint captures the current state; restoring the guard undoes the rewind.
preRewindCheckpoint: requireaborts the rewind when the guard cannot be captured. - Fixed-order transaction. Guard first, workspace second, config third, session replay fourth; every phase is logged; a failed restore leaves files, checkpoints, and session untouched.
workspaceRestore: 'reset-hard'is CC-equivalent and opt-in. It runsgit reset --hard <snapshot commit>(branch head moves to the snapshot commit; pre-snapshot history stays recoverable via reflog; untracked files untouched). It is off by default.- Model-visible ⟺ logged. Everything a user or model sees reconstructs from
command/run+command/done(and, once the host knows them,checkpoint/*events) plus the durablecheckpointsdomain. - Failures are loud. Invalid config throws at load; an unavailable domain, a failed restore, and a failed fork all return structured error text — nothing is silently swallowed or truncated.
Permissions & data
- Permissions: the workshop manifest declares
workspace:read,workspace:write,git:read,git:write,snapshot-storage:write,session-log:read,settings:write, andnetwork:none. - Data: checkpoint records live in the
checkpointsstorage domain (SQLite rows or a JSON file); copy snapshots live undersnapshotDir. The domain's global slot holds the per-session short-number counters, which is why deleting records (prune,clear,clear --all) can never recycle a number. Fully local — no network, no credentials. The domain is opened dual-version: 0.4.x-era media (domain v1) are opened in a compatibility mode that keeps old records readable and stores new captures in the v2 shape, so upgrading the plugin never orphans an existing medium. - Session log:
checkpoint/*events are appended through the adaptive gate; the authoritative audit chain iscommand/run+command/doneplus the durable domain.
Known limitations
- On rc.2,
checkpoint/*session events are suppressed by the adaptive gate; the audit chain ridescommand/run+command/doneplus the storage domain until a host ships the vocabulary or theignorableenvelope. confirmVia: approvalneeds an open turn, and commands run between turns — mount userQuestions (or setconfirmVia: userQuestions) on rc.2.- Session rollback forks a new child session at the checkpoint boundary; it never rewrites or truncates the original session.
workspaceRestore: 'reset-hard'moves the branch head to the snapshot commit; it is off by default.- A checkpoint captured before any closed turn has no replay boundary — session rollback then creates a fresh child session with empty context.
Interoperability with other DSH plugins
Verified against DSH 0.2.0-rc.2 (the runtime this README ships for) and the high-star plugin set surveyed on 2026-10-05.
This plugin does not interfere with other plugins, including the widely installed high-star ones:
- No tool-name collision. Every tool is namespaced; no bare name owned by a shipped tool or another plugin is registered.
- No service-key collision. It provides no service key at all, so it cannot collide on one.
- No slot collision. It registers no client slot key, so it cannot contend for a
shadows-shipped-uiseat. - No HTTP route collision. It registers no
webServerprefix. - No patch-layer collision. The bundle patch only
inserts its own row; it never overrides a built-in row'sconfig. - No global mutation. It does not patch prototypes, rewrite
process.env, or replace the global fetch dispatcher.
Shared event listeners are non-interfering by construction. It observes the ordering-sensitive events fs/edit-intent, fs/write-intent, tools/pre-execute with ctx.on() — Cordis's broadcast registration, where every listener runs and none can starve another. Every listener here delegates through next(), so the chain is never short-circuited, and a mutation is applied to the value next() produced rather than returned in its place:
tools/pre-execute— also used bycc-safety-net(1576★).
Static evidence: dsh-plugin-doctor K10–K13 report pass for every check on this repository.
Compatibility
| Surface | Status |
|---|---|
| Harness | DeepSeek Harness dsh-v0.2.1-alpha.1 (GitHub tag, verified 2026-09-25; npm pin 0.1.7-rc.2, peers >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0) (adapted 2026-10-04): the host removed @deepseek-ai/dsh-settings-file and replaced the ctx.settings namespace-registration surface with SettingsForms, which projects each Loader entry's Config into the Settings form and persists edits on the profile patch — plugin config fields are now declared volatile() and read live, strict typert codecs carry only their create() factory, and the rewind notice declares its own message-source kind. The legacy settings.register path is kept for 0.1.5-rc.2/0.1.6-alpha.2 hosts. Verified 2026-09-22 against the dsh-v0.1.7-alpha.1 checkout (typecheck against the alpha.1 type surface + full unit suite + assembled-headless integration). |
| Node | ^22.19.0 || >=24.0.0 |
| Platforms | All (host commands + listeners; optional Settings page timeline via the settings capability) |
| Model | Any (no model calls — snapshots and restores are deterministic) |
Ecosystem & quality
- Gitee mirror (sync mirror; GitHub is canonical)
- dshfind plugin page (installs and ranking)
- OpenSSF Scorecard report (driven by .github/workflows/scorecard.yml)
- dsh-plugin-doctor verification report (K10–K13 all
pass) - DSH Market (listed)
- 1024 store channel:
npm i -g dsh1024once, thendsh1024 plugin --profile web add dsh-checkpoint-rewind(counts toward the deepseek1024.com install ranking) - Ecosystem knowledge base — measured data, not marketing: plugin development guide · plugin-selection data · maintenance criteria
Development
npm install # node ^22.19 || >=24; peers pinned 0.2.1-rc.2
npm test # node --test test/**/*.test.mjs (provider suites incl.)
npm run test:integration # assembled-headless verification (test/integration/)
npm run check:readmes # five-language README consistency gate
npm run verify:self-contained # dependency specs resolve from the registry
npm run verify:artifacts # shipped files present + index.mjs importable
npm run lint # oxlint
No build step: pure ESM — index.mjs/lib/ are the published artifacts. The README images are generated programmatically by scripts/gen-readme-assets.py (Python + Pillow, two light/dark flow SVGs) and are safe to re-run.
| Path | Purpose |
|---|---|
index.mjs |
Plugin entry (the only host-face file): provider registration, event listeners, the /rewind command |
lib/ |
Zero-DSH-dependency pure functions and providers (lib/providers/); lib/domain.mjs is the only module allowed zod/DSH packages |
client/ |
Settings-page timeline (browser half) |
cordis.patch.yml |
Bundle declaration: insert the checkpoint-rewind row |
test/ |
Unit tests + test/integration/ assembled-headless verification |
docs/assets/ |
README images (hero banner + light/dark structure diagram) |
scripts/ |
Mechanical gates + the README asset generator |
ARCHITECTURE.md |
Three-role seam architecture and the full decision record |
Topics: deepseek-harness, dsh, dsh-plugin, rewind, checkpoint, snapshot, session-replay, session-fork, config-restore, workspace-safety, undo, cordis-plugin
Family & thanks
This project is part of the DeepSeek Harness plugin family from PerryLink (all Apache-2.0). If it is useful, a star helps the next person find it — nothing is gated behind it.
- @mahirhir — object-existence doctor probe (#16), liveConfig for
snapshotDir/excludeGlobs/verifyByHash(#17), live-session prune scoping (#18), missing-snapshot quota cleanup (#19), dynamic copy-provider config (#20). - @PerryLink — creator and maintainer: the three-state checkpoint model, the git/copy provider seam, the three-phase rewind transaction, the Settings page timeline, docs, CI/CD and releases.
- @tmpdot (rmUnlucky) — v1-medium dual-version compatibility (#8), lazy
storageDomainresolution (#9), checkpoint dedup reply hints (#10), and the$DSH_HOME-unset snapshot-dir bug report (#4). - @shipinliang — checkpoint panel wire-contract reports: the missing
acceptsUndefinedon thelimitparameter (#5) and the#depsprivate-field proxy failure (#6). - @hwz1456 — web-profile checkpoint-capture report (#3).
- @Andiii208 —
plugin_checkpublishing-spec report (#2). - @alexchenzl (Ashu) — DSH Directory listing invitation (#7).
License
Apache License 2.0 © 2026 dsh-checkpoint-rewind contributors
Links
More in this category
Tencent/WeKnora#dsh-weknora★ 37331
Four read-only tools over a WeKnora knowledge base: list knowledge bases, hybrid passage search, reassemble one document's chunks in order, and WeKnora's own cited RAG or ReAct-agent answer with a resumable session id.
DayuanJiang/next-ai-draw-io#dsh-plugin★ 36916
Draws draw.io diagrams in DeepSeek Harness through the next-ai-drawio MCP server: the link in the reply opens a live preview in the right sidebar, you can edit the diagram by hand, and each AI change is a version you can restore. Node.js 18+; npx downloads the MCP server on first use.
superdesigndev/treg★ 7889
Tool catalog for agents: search ~2,600 external endpoints (SEO and SERP, backlinks, social, people and company enrichment, ad libraries, scraping) by the task you want done, read each one's parameters and per-call price, then call it with the credential injected server-side. Ships the skill plus an MCP row that stays disabled until TREG_TOKEN is set.
T-Auto/dsh-ops★ 5766
Provides bash, PowerShell 7, and high-performance Rust tools for DSH on Windows to reduce token usage.
sixtysevenlf/dsh-blender-plugin★ 2051
Lets a DSH agent drive a local Blender over a direct TCP channel with 15 tools: viewport frames, custom-angle renders, Python execution, headless and job offload, transaction rollback, and a planning layer of 228 ops across 34 families.
yjl9903/AnimeGarden#dsh★ 1399
Anime Garden for DSH: search anime torrent resources from 動漫花園, 蜜柑计划, 萌番组 and ANi inside DSH — via chat, a sidebar panel with fansub and type filters, a seasonal calendar, and an in-app floating player.
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.