🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI
广告☁️ 云服务器特惠阿里云首购 8 折 · 腾讯云合作特惠
DeepSeek Harness Hub
← 返回列表

liyixuan201211/dsh-rewind

DeepSeek Harnessspec-screened扫描:中风险在 GitHub 查看 ↗
⚠ 装前注意

撤销 agent 对目录所做的改动。

基本兼容但装前注意:npm 同名包「dsh-rewind」归属 ljh-dot/dsh-rewind,装到的可能不是本插件 · 最近上游提交 2026/9/16 · 已提供中文文档

撤销智能体对目录所做的操作:内容寻址快照、一条命令回退,以及可撤销的撤销。适用于任何文件夹——无论是否使用 git。DSH 插件 + 技能,零依赖。

综合分
30.3
GitHub 分
30.3
用户评分
—
★ Stars
1
周下载量
—
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add liyixuan201211/dsh-rewind
npm 同名包「dsh-rewind」归属 ljh-dot/dsh-rewind,装到的可能不是本插件,改用 GitHub 源安装
信任档位:已验证本站已于 1 天前真实安装成功
是什么
dsh 原生插件 · chat
装得上吗
本站已真实安装成功(非静态推断)
安全吗
本站尚未对该插件做风险分级(暂未覆盖,不等同于无风险)
还在维护吗
活跃:最近一次提交在 9 天前

档位由下列信号合成:本站实装验证(真实安装,当前最高到 L4)· 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。下方各区块是它的证据明细。 验证判据与等级说明 →

🟢实装验证通过· 2026/9/24
由本站实装验证器在真实 dsh 环境安装成功,非静态推断。
数据截至 2026/9/20(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
安装兼容性检查⚠ 装前注意

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包dsh-rewind @ 0.11.12
✓Node 引擎要求 >=20 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

npm 同名包「dsh-rewind」归属 ljh-dot/dsh-rewind,装到的可能不是本插件

验证方式:npm registry 存在性 + package.json 静态校验 · 最后验证 2026/9/21 11:07:22

用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动

README

由 DeepSeek 最新模型翻译生成
dsh-rewind

撤销 agent 对目录所做的改动。

对任意文件夹进行内容寻址的快照——无论是否使用 git——只需一条命令即可回退,而且这个撤销本身还可以被撤销。

dsh plugin --profile web add github:liyixuan201211/dsh-rewind

无需安装即可试用:

npx --yes github:liyixuan201211/dsh-rewind --help

中文:把 agent 对目录做的改动撤回去。 它不依赖 git——未提交的、从未被 git 跟踪的、
甚至这个目录根本不是仓库,都能还原。它和 dsh-blastradius 是一对:那个在动手前告诉你
"会毁掉什么、还能不能拿回来",这个在毁掉之后把它拿回来。它自己的撤销也能被撤销:
undo 会先把当前状态存成快照再动手,并把那个 id 打给你。

它填补的空白

git checkout . 听起来像是撤销。但对于真正会发生的情况,它并不是:

| agent 做了什么 | git 有记录吗? | rewind undo |
|---|---|---|
| 编辑了已跟踪的文件,未提交 | 没有——只有最后一次提交 | 恢复这些编辑 |
| 删除了一个从未提交过的文件 | 没有 | 恢复该文件 |
| 删除了一个从未被跟踪的文件 | 没有 | 恢复该文件 |
| 在一次糟糕的 codemod 中创建了 40 个文件 | 它从未见过这些文件 | 移除全部 40 个 |
| 对你的构建脚本执行了 chmod -x | 没有 | 恢复权限模式 |
| 在一个不是仓库的目录中运行 | — | 同样有效 |
| 从模板重写了 .env | 没有 | 恢复内容 |

git 记录的是提交。它不记录你一小时前工作树的状态,也从未见过你尚未添加的文件。而这正是 agent 操作的窗口。

核心思想:撤销本身可被撤销

在 undo 触碰任何东西之前,它会先对即将被替换的状态做一次快照——并打印出那个 id。所以你刚刚回退掉的东西并没有消失;回退到它就能把它原样放回。

$ rewind undo --yes
undo complete — 3 restored, 1 removed

the state you just replaced is 20260914T104302Z-9f31
rewind undo 20260914T104302Z-9f31 puts it back

这正是让它在出问题时可以放心使用的原因。另外两个特性补足了其余部分:

- 绝不递归删除。 撤销只会移除它捕获的那些文件,然后仅在目录为空时才请求移除该目录。它移除的目录里的 node_modules/ 会保留下来,输出中也会说明这一点。
- 字节从未被捕获的路径绝不会被删除。 如果某个文件在拍摄快照时太大或无法读取,删除它就无法被撤销——因此整个撤销会被拒绝,而不是执行到一半。

使用示例

$ rewind snap --label "before the refactor"
snapped 20260914T104255Z-44a0  /home/me/project
3 files, 2 directories, 51 B
rewind undo 20260914T104255Z-44a0 puts it back

... an agent rewrites the tree ...

$ rewind status
4 paths differ from 20260914T104255Z-44a0 (12s ago)

build.sh       18 B (mode 755 → 644)
docs/guide.md  removed  8 B
src/app.js     25 B (content changed)
src/helper.js  added    30 B

rewind diff   see what changed
rewind undo   go back to 20260914T104255Z-44a0
rewind snap   accept the current state and move on

$ rewind undo
Restoring 20260914T104255Z-44a0: 3 restored, 1 removed
删除   src/helper.js  30 B
恢复   build.sh       18 B
恢复   docs/guide.md  8 B
恢复   src/app.js     25 B

没有任何更改——没有显式的 --yes,什么都不会被应用。
rewind undo 20260914T104255Z-44a0 --yes

不带 --yes 的 undo 不是错误,也不是空操作:它是打印出来的计划,
其退出码表示什么都没发生。

包装命令,而不是靠记忆

纪律是任何快照工具最薄弱的环节,因此最常见的情况——一条命令重写许多文件——有一个包装器:
bash
rewind exec -- npx jscodeshift -t transform.js src/
rewind exec -- rm -rf build/ dist/

它在命令执行前做快照,在你的终端中运行命令,执行后再做快照,并打印
执行前状态的 id。它以该命令的退出码退出,因此在管道或脚本中使用是安全的。
撤销一条被包装的命令只需一个 id,而不是你必须去猜的时间戳。

对于长时间会话,可以让保护持续运行:
bash
rewind watch --debounce 2000

事件会被合并,并由一个内容寻址的清单决定是否真的发生了变化,因此空闲时的一次
检查只需一次比较,且不写入任何日志行。

存储

内容寻址,位于 /.rewind/:

meta.json              这个存储属于哪个根目录,以及它的捕获策略
log.jsonl              每个快照一行,仅追加
objects//  文件内容,在所有快照之间去重
manifests/     每个不同树状态对应一个规范 JSON 树
stat.json              使重新扫描变得廉价的大小+mtime 缓存

按内容哈希寻址会带来两个特性:

- 快照很廉价。 一个被编辑十次的文件只存储一次;未更改的树的两个快照
共享一个清单,因此成本仅为一行日志。
- 恢复是可验证的。 对象的名称是其内容的哈希,因此恢复时会重新哈希它读取的内容,
并拒绝将不匹配的字节写入真实文件。

任何内容都不会被就地覆盖:对象使用 O_EXCL 写入,文件通过临时文件
和重命名来恢复,日志以追加方式写入。

捕获什么,不捕获什么

捕获:每个不超过 8 MiB 的常规文件、目录(包括空目录)、
符号链接(记录为链接,绝不跟随)以及权限位。

排除:.git、node_modules、.venv、__pycache__、dist、build、
target 以及 DEFAULT_EXCLUDED_NAMES 中的其余项,外加根目录中的
.rewindignore 或 --exclude 匹配的任何内容。

未被捕获的路径,就是撤销时拒绝删除的路径。 这正是该列表存在的全部理由——
排除是一条安全边界,而不是速度优化。该策略在存储创建时写入 .rewind/meta.json,
并被之后的每条命令读回,因此快照和之后的撤销不可能对树中包含什么产生分歧;
而且该策略只会变得更具保护性,因此删除一条排除规则绝不会变成一次撤销,
删除存储中没有副本的文件。

安全属性,每项都有测试

| 属性 | 为什么存在 |
|---|---|
| 拒绝操作不会改变任何东西 | 半途而废的撤销会留下两个需要推理的损坏状态 |
| 不会递归删除任何内容 | 快照从未捕获的内容必须保留下来 |
| 未捕获的内容永远不会被删除 | 它无法被放回,所以删除它就不是可撤销的 |
| 撤销本身是可撤销的 | 被替换的状态会先被快照,并打印其 id |
| 已修改的文件永远不会先删除再重建 | 失败的恢复不能已经破坏了该文件 |
| 内容在写入之前会被验证 | 损坏的对象不能悄无声息地变成你的文件 |
| 写入是原子的 | 被中断的撤销永远不会留下半个文件 |
| 符号链接会被记录,永远不会被跟随 | 链接不能拉入或写出根目录之外的任何内容 |
| 每一次删除都先于每一次写入 | 符号链接会在其下创建任何内容之前被解除链接 |
| 清单必须在结构上一致 | 缺失的父级会被拒绝,而不是即时创建 |
| 不会写入根目录之外的任何路径 | 清单是 JSON;恶意的清单会被拒绝,而不是被遵循 |
| 捕获策略只会增长 | 删除一条规则不能使旧路径变得可删除 |
| 存储以仅所有者权限创建 | 它保存着文件内容的明文副本 |

这些在 test/safety.test.js 和 test/undo.test.js 中被断言——用
node --test test/safety.test.js test/undo.test.js 单独运行它们。每项背后的推理写在
skills/rewind/reference/safety.md 中。

退出码就是契约

| 代码 | 含义 |
|---|---|
| 0 | 成功 |
| 1 | 应用时出错——某些路径可能未被恢复 |
| 2 | 用法错误 |
| 3 | status:目录树与上一次快照不同 |
| 4 | undo:计划已就绪,但未给出 --yes——没有任何改变 |
| 5 | 拒绝:不安全的路径,或从未被捕获的内容——没有任何改变 |
| 6 | 无事可做:已经处于该状态——没有任何改变 |

4、5 和 6 都意味着什么都没发生,它们被分成不同的数字,这样“我选择不行动”就永远不会被误认为“我行动了但失败了”。
bash
rewind status -q || echo "the tree has moved"

命令
bash
rewind snap [--label "before X"]      # snapshot now
rewind log [--limit 100]              # what snapshots exist
rewind status                         # what differs from the last one (exit 3 if anything does)
rewind diff [] [--stat] [-- P]   # the changes themselves
rewind undo [] [--yes] [--force] # put it back (prints the plan first, always)
rewind show :              # one file as it was
rewind exec --               # snapshot, run, snapshot
rewind watch [--debounce 2000]        # snapshot on every change
rewind prune [--keep 20] [--older-than 7d]
rewind doctor [--verify]              # can every snapshot still be restored?
引用:last(默认值)、@2(往回两次)、一个 id 或唯一前缀、14:32,或
2026-09-14。完整细节见
skills/rewind/reference/commands.md。

作为 DSH 插件安装
bash
dsh plugin --profile web add github:liyixuan201211/dsh-rewind

这会安装该技能(skills/rewind/),它教会 agent 在风险变更前做快照,将风险命令包裹在 rewind exec 中,并逐步推进到 undo --dry-run → undo --yes,而不是一上来就用 undo。

该 bundle 补丁对启动图没有添加任何东西——cordis.patch.yml 存在、有效,且是惰性的。整个执行面就是那个空文件、package.json(没有生命周期脚本)、src/ 中的 CLI,以及 SKILL.md 的说明文字。一个以让副作用可逆为主题的工具,没有理由在启动层成为一个不可逆的新副作用。

诚实的定位

这不是第一个能恢复文件的程序,那么它到底是什么?

| | 它覆盖什么 | 它在哪里止步 |
|---|---|---|
| git | 已提交的内容 | 工作树、未跟踪文件、非仓库 |
| Time Machine / 卷快照 | 整个磁盘,每小时 | 粒度粗、依赖操作系统、恢复单个目录很别扭 |
| restic / borg / rsync | 备份到另一位置 | 需要仓库设置、加密配置,并非针对“撤销最近 5 分钟” |
| 编辑器/agent 检查点(Claude Code、Cursor 等) | 该工具在该会话中所做的编辑 | 受厂商和会话限制;存储不归你读取 |
| rewind | 任意目录、任意进程、当下 | 它没有时间旅行:没有快照就没有可恢复的东西 |

这个细分定位是刻意狭窄的:本地、即时、按目录、厂商中立、零依赖的撤销,其存储是你可以用 ls 检查的普通文件。 在 GitHub 上搜索这种形态的、内容寻址的快照/撤销 CLI,基本一无所获,这要么是机会,要么是警告;诚实的答案是,这种需求通常被 git stash 和 cp -r 糟糕地满足。

它刻意不是备份。存储位于同一磁盘上的同一目录中。它防范的是糟糕的编辑,而不是磁盘损坏。

它诚实承认自己不知道的事

- 没有时间旅行。 如果在变更前没有做快照,就没有可回退的东西。rewind watch 的存在,就是为了让这件事不再是你必须记住的事。
- 超过大小限制的文件会被记录,但不可恢复。 snap 在发生时就会说明;撤销计划在关键时会显示 can't。
- 存储保存文件内容的明文副本,包括 .env 和密钥。让它远离版本控制(.gitignore 已说明),在共享机器上要留意。没有加密。
- 被忽略的路径不受任何其他保护。 它不会碰你的 node_modules,也无法恢复它。
- 快照不是提交。 恢复旧快照会故意丢弃它之后的所有内容,包括他人的工作。
- 大型仓库会占用磁盘。 去重是精确的,因此成本是不同文件版本的总和,但这仍然是所有内容的第二份副本。

开发

需要 Node >= 20。使用带 JSDoc 类型的纯 ESM JavaScript:没有构建步骤,没有安装时脚本,并且发布的 bin 在安装后确实可以运行——CI 通过打包 tarball 并从真实的 node_modules 中运行它来断言这一点。
bash
npm test            # 108 tests
npm run typecheck   # tsc --noEmit over the JSDoc types
npm run check       # both
./examples/demo.sh  # end to end, asserting every exit code

src/
cli.js         the exit-code contract and argument parsing
config.js      what is captured, the ignore rules, and the stored policy
scan.js        walking the tree: content hashes, symlinks, what cannot be read
store.js       content-addressed objects, manifests, the append-only log
snapshot.js    scan → manifest → one log line
plan.js        comparing two manifests; the undo plan and every refusal
undo.js        preflight, snapshot the present, apply, verify
diff.js        a unified diff, capped and honest about being capped
refs.js        naming a moment: last, @2, an id, 14:32
exec.js        snapshot, run, snapshot
watch.js       debounced automatic snapshots
prune.js       mark and sweep
doctor.js      can this store still do what it promises?
report.js      human output

CI 在 Node 20/22/24 上运行测试套件,将打包的 tarball 安装到真实的 node_modules 中并用它恢复文件,单独运行安全属性测试,运行演示,并检查 src/ 不包含网络导入,以及 package.json 未定义任何生命周期脚本。

许可证

MIT。

上游仓库有新提交时邮件通知你(每天最多一封,无更新不打扰),随时一键退订。

💬 加入社群

插件用法、部署报错、新插件第一时间同步——群里问,比一个人翻文档快。

DPharness QQ 群二维码,QQ 扫码进群
QQ 扫码进群
DPharness 飞书群二维码,飞书扫码进群
飞书扫码进群