← 返回列表
⚠ 装前注意
撤销 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-rewindnpm 同名包「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。