Passer au contenu principal
Z

deepseek-harness-rewind

zoyluoblue/deepseek-harness-rewind

DeepSeek Harness (dsh) plugin that snapshots your workspace at every turn into a shadow git repository, so you can restore the files to any earlier turn. Your own .git is never touched, and plain directories work too.

Installer

dsh plugin --profile web add github:zoyluoblue/deepseek-harness-rewind

README

@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.

The Rewind page in dsh Settings, listing each turn of a DeepSeek Harness session with the files it changed and a Restore button


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, and gc are 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 dsh Rewind confirmation dialog, warning that newer files will be deleted before restoring a snapshot

The /rewind command

Costs no tokens and runs no model turn — it is handled by the harness, not sent to the model.

CommandWhat it does
/rewindRestore the previous turn of this session
/rewind 3Restore the end of turn 3
/rewind a1b2c3d4Restore a snapshot by id (a unique prefix of 4+ characters)
/rewind listList this workspace's snapshots
/rewind saveSave 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'
OptionDefaultMeaning
gitTimeoutMs60000Deadline for one git command. Raise it for very large workspaces.
excludescommon dependency and build directoriesExtra paths never saved, applied to every workspace on top of your .gitignore. Set to [] to rely on your .gitignore alone.
retentionDays30Sessions whose newest snapshot is older than this are dropped.
maxSessions50How many sessions to keep per workspace, newest first.
listLimit200Most 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.

ValueThe 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 .gitignore are not saved or restored. If the agent breaks .env or something under node_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.
  • git must 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 /rewind is refused while the agent is mid-turn. Those paths wait for an idle agent. The opt-in rewind_restore tool 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.
  • excludes applies to every workspace, not only to directories without a .gitignore. A project that tracks dist/ or build/ in git will not have those files captured or restored unless you set excludes: [].

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 addwrite-treecommit-treeupdate-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

  • git available where dsh runs tools
  • Node ^22.19 || >=24
  • DeepSeek Harness (developer preview — expect breaking changes)

License

MIT

Plugins associés