deepseek-harness-rewind
dsh plugin: snapshot your workspace every turn and restore the files to any earlier point. A rewind/undo for DeepSeek Harness coding sessions — your own git repo is never touched.
- Stars
- 0
- Language
- TypeScript
- Created
- Aug 19, 2026
- Updated
- Aug 19, 2026
Introduction
@zoytown/dsh-rewind
English | 中文
Put the files back. A DeepSeek Harness plugin that
saves your workspace at the end of every turn, so when the agent takes a wrong turn you can restore
the files to any earlier point — from the Settings page or with /rewind.
Your own git repository is never touched. Directories that are not git repositories work too.

Why
The agent has been editing for six turns. Turn 3 was right; turns 4 through 6 made it worse. You want turn 3 back.
git cannot help: you have not committed since turn 1, and the agent's intermediate states were never
commits in the first place. git checkout . throws away everything, including the parts that were good.
The harness does not save workspace files anywhere — its built-in checkpointing (dsh-session-checkpoint-policy)
governs when the session log becomes durable and has nothing to do with your files.
This plugin fills that gap.
What it does
- Saves every turn. When a turn ends, the workspace is committed into a shadow repository of the plugin's own. Turns that changed nothing cost one tree comparison and produce no entry.
- Restores any turn. Files edited since then are reverted, files created since then are deleted — the workspace becomes that state rather than having it layered on top.
- Every restore is reversible. The state being overwritten is saved first, so an unwanted restore is undone by restoring the entry above it.
- Never touches your git. Snapshots live in
$DSH_HOME/rewind/, not in your.git. Your index,HEAD, stashes, reflog, andgcare outside the blast radius, and a plain directory gets the same protection a repository does.
Install
npx -y @deepseek-ai/dsh plugin --profile web add @zoytown/dsh-rewind
Then restart dsh. A Rewind entry appears in the Settings sidebar.
Requires git on the machine. Without it the plugin reports that snapshots are paused and everything
else in dsh keeps working.
To remove it:
npx -y @deepseek-ai/dsh plugin --profile web remove @zoytown/dsh-rewind
Snapshots outlive the plugin; delete $DSH_HOME/rewind/ to reclaim the space.
Using it
The Settings page
Settings → Rewind lists every saved point for the current workspace, newest first, with what changed and which tools ran. Restore asks for confirmation, spelling out that newer files will be deleted, then puts the files back.
The badge marks the snapshot your files currently equal — after a restore it moves to the restored entry, not the newest one.

The /rewind command
Costs no tokens and runs no model turn — it is handled by the harness, not sent to the model.
| Command | What it does |
|---|---|
/rewind | Restore the previous turn of this session |
/rewind 3 | Restore the end of turn 3 |
/rewind a1b2c3d4 | Restore a snapshot by id (a unique prefix of 4+ characters) |
/rewind list | List this workspace's snapshots |
/rewind save | Save the current state now, outside a turn |
A restore prints the id of the state it overwrote, so /rewind <that id> undoes it.
What is and is not saved
Snapshots respect your .gitignore, so ignored files — .env, build output, node_modules — are
not saved and not restored. This keeps snapshots small, and it means a restore leaves those files
exactly as they are.
On top of that, the excludes list below is applied to every workspace, git repository or not. It
exists so a directory with no ignore rules of its own does not swallow node_modules, but it is not
conditional: a project that deliberately tracks dist/ or build/ in git will not have those captured
either. Set excludes: [] if you want nothing beyond your own .gitignore.
.git itself is always excluded and cannot be configured otherwise: saving it would double the size of
every snapshot, and restoring it would overwrite your real commit history with a stale copy.
Configuration
Edit the dsh-rewind row in your profile's cordis.yml:
- id: dsh-rewind
name: '@zoytown/dsh-rewind'
config:
gitTimeoutMs: 60000
retentionDays: 30
maxSessions: 50
listLimit: 200
exposeTool: 'off'
| Option | Default | Meaning |
|---|---|---|
gitTimeoutMs | 60000 | Deadline for one git command. Raise it for very large workspaces. |
excludes | common dependency and build directories | Extra paths never saved, applied to every workspace on top of your .gitignore. Set to [] to rely on your .gitignore alone. |
retentionDays | 30 | Sessions whose newest snapshot is older than this are dropped. |
maxSessions | 50 | How many sessions to keep per workspace, newest first. |
listLimit | 200 | Most snapshots shown at once. |
exposeTool | 'off' | Whether the model can use rewind. See below. |
Letting the agent rewind itself
exposeTool is 'off' by default, which keeps rewind a human-only capability.
| Value | The agent can |
|---|---|
'off' | nothing — rewind is yours alone |
'read-only' | read its own history (rewind_list) |
'full' | also restore the workspace (rewind_restore) |
'full' is genuinely useful — "this approach is wrong, put the files back and start over" is a recovery
move no amount of prompting replaces — and genuinely risky: an agent that misjudges can discard work you
wanted. Every restore still saves the overwritten state first, so it is reversible, but the decision to
enable it should be yours and deliberate.
FAQ
How do I undo what the agent just did to my files?
Type /rewind. It restores the workspace to the end of the previous turn. If you want a specific point,
/rewind list shows every saved turn and /rewind 3 restores turn 3.
Does this commit to my git repository?
No. Snapshots go into a separate repository under $DSH_HOME/rewind/, and your .git is never opened
for writing. Your index, HEAD, stashes, and reflog are unchanged, and git status shows exactly what
it showed before.
Does it work if my project is not a git repository?
Yes. The shadow repository is the plugin's own, so your directory does not need to be a repository — this is the case rewind protects best, because there is nothing else protecting it.
Does rewinding undo the conversation too?
No. Rewind restores files only. The session log is append-only by design in DeepSeek Harness, and the transcript stays exactly as it was — so after a restore the agent still remembers what it did, which is usually what you want when telling it to try a different approach.
I installed it but there is no Rewind page. What now?
Restart dsh — plugins are mounted at boot. If it is still missing, run
npx -y @deepseek-ai/dsh --profile web --dump-config and check that a dsh-rewind row appears; if it does
not, the package was installed as a plain dependency rather than a bundle.
Will it slow down my turns?
No. Snapshotting runs after the turn ends and is never awaited by the agent loop, and a turn that changed no files costs one tree comparison and stores nothing.
How much disk does it use?
Snapshots share storage the way git commits do: unchanged files are stored once. The cost of a workspace is
roughly one copy of it plus the changes since. Sessions older than retentionDays (30 by default) are
deleted automatically.
Can the agent rewind by itself?
Only if you turn it on. exposeTool is 'off' by default; set it to 'full' to let the agent restore
the workspace, or 'read-only' to let it read its history without restoring.
Known limitations
- Files ignored by
.gitignoreare not saved or restored. If the agent breaks.envor something undernode_modules, rewind cannot bring it back. - A restore does not touch the conversation. Files go back; the transcript does not.
- Retention is per session, not per snapshot. A single very long session keeps all of its snapshots; the limits drop whole sessions once they are old or too numerous.
- Sandboxed or remote subprocess providers are not supported in 0.1. The shadow repository is created on the machine dsh runs on, so a provider that executes tools elsewhere (E2B) would snapshot the wrong filesystem. The default local provider is what this version targets.
gitmust be installed. Without it the page says snapshots are paused; nothing else in dsh is affected.- Files inside a nested git repository are not captured. A sub-repository is recorded the way git records one — as a pointer, not as files — so rewind neither saves nor restores anything inside it.
- Restoring from the panel or
/rewindis refused while the agent is mid-turn. Those paths wait for an idle agent. The opt-inrewind_restoretool is the deliberate exception: the agent calls it during its own turn, so that path does not wait (it is barred from running beside other tool calls instead). - A restore interrupted partway — a git timeout, a killed process — can leave the workspace between the two states. The safety snapshot is always written first, so nothing is lost: re-running the restore, or restoring the safety entry, settles it. But do not read an error from a restore as a guarantee that nothing on disk moved.
excludesapplies to every workspace, not only to directories without a.gitignore. A project that tracksdist/orbuild/in git will not have those files captured or restored unless you setexcludes: [].
How it works
Each workspace gets a git repository under $DSH_HOME/rewind/<key>/repo.git, bound to your directory
with --work-tree. Saving is add → write-tree → commit-tree → update-ref, which writes only
inside that repository: no file in your workspace is touched and no HEAD moves. Restoring is
read-tree -m -u, which makes the workspace equal the snapshot — including deleting files the snapshot
does not have.
Every git command runs with hooks disabled, signing disabled, and your global excludes neutralized, so your repository's own hooks never fire and a signing passphrase is never demanded. Git runs through the harness's subprocess service, so it executes wherever your files actually live.
Sessions are separate chains inside one workspace repository, so they share storage while staying individually restorable and individually expirable.
Privacy
Nothing leaves your machine. The plugin has no telemetry and makes no outbound network requests.
Its two HTTP routes are local surfaces for the Settings page, and both require the request to arrive over
the loopback interface and to address the server by a loopback Host — the second check is what a
DNS-rebinding page cannot satisfy. The restore route additionally requires POST and refuses a request
labelled cross-site. Anything already able to run code on your machine as you can, of course, reach them,
exactly as it could reach dsh itself.
Verified
The behaviour described above was exercised on 2026-08-19 against DeepSeek Harness packages
0.1.0-rc.6/0.1.0-rc.7 and git 2.50.1, including a full save → restore → undo cycle through the
Settings page. DeepSeek Harness is a developer preview; re-check these claims after a harness upgrade.
Requirements
gitavailable where dsh runs tools- Node
^22.19 || >=24 - DeepSeek Harness (developer preview — expect breaking changes)
License
MIT