dsh-filesnap
开发工具 活跃维护

dsh-filesnap

extracurricular-ai/dsh-filesnap

Rust核心开发,可快速回退或重做指定轮次的对话及对应文件修改,无需依赖git仓库,操作简单高效,满足日常变更回溯需求。

41
Stars 标星
9
Forks 分支
41
Watchers 关注
1
Open Issues
TypeScript
主要语言
Apache-2.0
开源协议
1.2 MB
仓库大小
25 天前
最后推送
一键安装扩展 / 插件指令
dsh plugin --profile web add github:extracurricular-ai/dsh-filesnap
git clone https://github.com/extracurricular-ai/dsh-filesnap.git
git clone git@github.com:extracurricular-ai/dsh-filesnap.git
README.md main

dsh-filesnap — rewind DSH conversations and files together

npm
CI
licence
powered by 🦀 Rust
git not required

English | 中文

Join the discussion ·
Report a bug

Rewind a DeepSeek Harness
conversation and its workspace together — without touching Git. Every rewind
happens in a fork, so /redo can take you back if you change your mind.

dsh-filesnap: conversation and workspace rewind together

> /rewind 2
Rewound to turn 2 (make the rate limit per-tenant).
Files: 7 written, 1 deleted.

The conversation continues in session-9f3c1a04-….
Run /redo there to reverse this rewind.

Quick start

Requirements

  • DeepSeek Harness with a web or headless profile
  • Node.js ^22.19 or >=24
  • Linux, macOS or Windows on x64 or arm64

The native filesnap binary is
installed with this package. You do not need Rust, Git or a separate runtime.

[!IMPORTANT]
dsh does not yet provide a supported registration API for event types declared
by out-of-repository plugins. dsh-filesnap therefore registers its session
events at load time. If you uninstall the plugin, sessions it captured will
not open until you reinstall it.
Their data remains intact on disk. See
the architectural limitation.

1. Install

$ dsh plugin --profile web add dsh-filesnap

The launcher may warn that this package has no dsh.bundle. That is expected:
dsh-filesnap is mounted as a plugin row rather than a profile layer.

2. Enable it

Add this row to ~/.dsh/profiles/web/cordis.patch.yml:

- insert:
    - id: filesnap
      name: dsh-filesnap

For headless use, replace web with headless in both the command and profile
path.

3. Verify and use

$ dsh --profile web --dump-config | grep -A 1 filesnap
- id: filesnap
  name: dsh-filesnap

Restart the profile, run one agent turn, then enter /rewind. If the plugin is
not listed in the composed profile or the browser control is missing, follow the
troubleshooting guide.

Why dsh-filesnap

What it means
Conversation + files A rewind forks the transcript at the selected turn and restores the workspace into that fork.
Git-independent Works in repositories and ordinary directories. Commits, branches, stash and worktree state are never changed.
Undoable rewind A rescue point is captured before restore writes begin; /redo reverses the rewind.
Broad file coverage Handles binary files, ignored files and edits made through ctx.fs outside the project root.
Native engine Bounded scanning, content addressing and restore run in a small 🦀 Rust binary outside the session's Node process.
Inspectable /rewind status reports storage use and files that are not protected, with the reason for each exclusion.

The design does not treat version control as a snapshot store. For a
version-stamped, source-audited comparison with other dsh rewind plugins, see
Comparison.

Commands

Command Result
/rewind List the workspace state captured before each turn.
/rewind <turn> Fork the conversation at that turn and restore its files.
/redo Reverse the rewind that landed in the current session.
/rewind status Report stored data and files that are currently unprotected.

/rewind accepts the displayed turn number or a point id. Relative addressing
such as “go back three” is deliberately not supported: a restore overwrites
files, so the target must be explicit.

Both commands dispatch without a model turn. Rewinding is something you do to a
conversation, not a request that should pass through the conversation being
rewound.

What gets protected

Before every model step, dsh-filesnap captures a bounded union of:

  • files already known to the workspace, including Git-tracked names;
  • paths observed immediately before a ctx.fs write or edit, even outside the
    project root;
  • a bounded scan of recent workspace changes, which covers writes made by shell
    commands.

Content is addressed by hash, so unchanged files are reused rather than copied
once per turn. .filesnapignore is symmetric: an ignored path is never stored,
restored or deleted by a restore. A restore deletes a path only when the target
snapshot positively recorded that the path was absent.

/rewind status re-scans the current tree and names anything outside coverage,
such as an unreadable path, an oversized file or a non-regular file. Coverage
details and restore invariants live in Architecture.

Performance

The engine runs once before a model request that normally takes seconds. The
current preliminary measurements, taken with a warm page cache, are:

Workspace Files captured First capture Repeat capture
this repository 84 20 ms 8 ms
DeepSeek Harness monorepo 7,995 of 70,918 on disk 1.75 s 268 ms

These numbers describe their original machine, not a universal promise. The
tracked set is bounded instead of walking all 70,918 files every turn, and the
repeat capture reuses unchanged content. See Benchmarks
for the method, missing metadata and a reproducible command sequence.

Browser experience

The optional ./client export adds:

  • a rewind action beside the existing actions on each completed assistant turn;
  • header actions for redo and store status.

The transcript is already the list of turns, so the plugin does not add a
second checkpoint panel. In the browser, the deployment creates the correctly
composed child session, the host restores files into it, and the client opens
that child. Headless use performs the fork in the host plugin.

The browser bundle is typechecked and built during release. It does not yet have
an automated in-browser test; that remains a tracked limitation.

Configuration

Defaults are intended to work on an ordinary local deployment.

Field Default Purpose
command resolved automatically Use another engine build, or a bare command resolved by a remote subprocess provider.
dataDir platform data directory Store location; never inside the project.
timeoutMs 120000 Wall-clock limit for one engine invocation.
graceMs 2000 SIGTERM-to-SIGKILL grace period after cancellation or timeout.
maxOutputBytes 1048576 In-memory limit for each collected output stream.
declareEdits true Record file pre-images immediately before edits.

Unknown keys and unusable values fail at plugin load rather than silently
removing a later rewind point.

Current limits

  • Uninstalling the plugin makes sessions containing its event types unreadable
    until it is reinstalled; no session data is deleted.
  • Typing /rewind into the web composer reports the child session id instead of
    navigating to it. The per-turn browser action performs the navigation.
  • A host-performed headless fork inherits the model route and preset, but not the
    deployment's per-agent model selection or workspace attachment.
  • Shell-created files outside the workspace, above the engine size bound or
    outside the recent-change budget require an observed filesystem write to be
    covered.
  • gc, doctor and session deletion exist in the engine but are not yet exposed
    as /rewind subcommands.

See Architecture for the event-registration constraint
and Troubleshooting for operational workarounds.

Documentation

Document What it answers
Architecture When captures happen, how forks and restores are ordered, and what is recorded.
Comparison How the available dsh rewind designs differ, with dated package versions.
Benchmarks What the published timings mean and how to reproduce them.
Troubleshooting Installation, profile, client bundle and storage diagnostics.
Contributing Local development, builds and the four test tiers.

The snapshot engine is also usable outside dsh through Rust
(cargo add filesnap) or its versioned JSON Lines CLI. The complete subprocess
adapter in this repository is src/cli.ts.

Contributing

Issues, discussions and pull requests are welcome in English or Chinese:

Read CONTRIBUTING.md before changing the host/engine boundary.
Report security problems through SECURITY.md, not a public issue.

Licence

Apache-2.0. See LICENSE. The
filesnap engine uses the same
licence.