
Security News
Deno Goes the Way of the Dinosaur
Cloudflare is acquiring Deno’s team, which will provide another year of bug fixes and security updates before ending support for the runtime.
dsh-checkpoint-diff
Advanced tools
File-diff visualization between checkpoint time nodes for DeepSeek Harness: a read-only timeline + per-file line diff over the dsh-checkpoint-rewind checkpoints storage domain, with preview-first rollback (restore workspace files from any time node, singl
English version: README.en.md
把 dsh-checkpoint-rewind 的检查点(快照)当作时间节点,提供任意两个节点之间的文件差异可视化:会话头部 "Diff" 按钮打开浮层面板(时间线 → 文件清单 A/M/D → 逐行 diff),另有 /diff 命令与 JSON HTTP API 供 headless 使用。
只读设计,唯一显式例外是回滚:可从任意时间节点把工作区文件恢复回来(整节点或单文件),经面板、/rollback 命令或 API 触发。回滚只覆盖写、绝不删除(节点之后新建的文件保留并报告)、绝不碰 .git/.dsh、绝不写快照存储/git/会话。"绝不删除"的唯一例外是回滚的单次撤销(/rollback --undo、面板按钮):只删除恢复操作自己刚创建的文件,其余一律不动(进程内记忆,重启即失效)。
[!IMPORTANT] 先装上游,再装本插件。 本插件是只读消费端——检查点(快照)由上游 dsh-checkpoint-rewind(快照生产者)产生,本插件自身不产生快照。只装
dsh-checkpoint-diff而漏掉上游,检查点时间线是空的:Diff 按钮、/diff、回滚都没有数据(只有 Trace (session log) 范围可用)。安装见安装。
场景。 AI 代理在替你写代码、改文件。它的"思考"是黑盒,但它的行动会落到你的工作区:它改了什么?什么时候改的?改坏了怎么办?——这些问题不能没有答案。
立场。 这类工具通常有两条路:一是替你省事——自动总结、自动判断、替你过滤信息;二是让你安心——把真相原样交给你,保证你随时能查清、能追究、能退回去。本插件明确选择第二条路:不做"替你看"的总结与过滤,而是把看清楚和退回去的能力完整交到你手里。
一句话:你可以不看,但它不能不可查。 人可以不看不追究,但绝不能没有看和追究的手段——这就是本插件存在的理由。
全部为真实截图(运行在真实 harness 会话上)。面板全貌——scope 切换、from/to 时间节点下拉(意图标签 + (HEAD) 前缀)、目录树文件清单(A/M/D)、逐行 diff(红删绿增 + ↑/↓ 变更块跳转)、Restore workspace 恢复卡片:

Trace (session log) 范围——会话日志重放 + 三泳道拖选时间线(Input / Model / Tools span、turn 边界;拖选区间自动映射为 from/to 边界节点):

本会话 范围——当前会话的检查点时间线,选择要回滚的版本,点击“Preview Restore”预览效果:

本项目 范围——跨会话合并 + fork 血缘分支下拉:

UI 每次大改后必须重新截图并更新本文(采集规则见 docs/screenshots/README.md)。
/diff 列出本会话时间线——rewind 在每次变更工具执行前自动留下快照时间节点(格式与真实输出一致,数据为示意):
diff: 3 checkpoint(s) for this session
#a1b2c3d4 20m ago turn 2 step 1 copy 3 file(s) 18 KiB edit lib/engine.mjs
#b2c3d4e5 10m ago turn 3 step 1 copy 2 file(s) 12 KiB edit README.md
#c3d4e5f6 5m ago turn 3 step 2 copy 4 file(s) 25 KiB bash pnpm test
usage: /diff <from> <to> (id prefix or "latest" for either side)
/diff <from> <to> 任意两节点:变更文件摘要 + 逐行 diff(GUI 面板中同屏显示红删绿增):
diff: #b2c3d4e5 (14:02 · edit README.md) → #c3d4e5f6 (14:07 · bash pnpm test)
4 file(s) changed: +1 added, 2 modified, 1 deleted
M lib/engine.mjs
- function lcs(a, b) {
+ function lcs(a, b, opts) {
M README.md
- 只读设计,唯一例外是回滚
+ 只读设计,唯一显式例外是回滚
A test/engine.test.mjs
D lib/legacy.mjs
/diff / HTTP API),并提供预览式回滚(只覆盖写、绝不删除、可撤销)。/diff · /rollback · /checkpoint-diff/api。#短id、时间、turn/step、provider、触发工具;/rewind 守护检查点带标记)。/rewind fork 血缘组织:分支下拉(根 + 旁支,会话标题)、会话标签、fork / 根缺失标记;可选 dsh-session-query 服务缺席时退化为扁平合并。(turn, step) 的 tool/call 事件解析出 edit README.md、bash pnpm test 之类的标签(GUI、/diff 输出、JSON API 一致);文件目标相对化到工作区(超长退化为文件名)、命令简写为"命令名 + 首参"、str_replace_editor 显示为 edit、只读工具带 Ⓡ 标注;日志缺失回退原始触发工具。trace 时间线的 tooltip 还会附上该工具前一条 assistant 消息的说明文本(引号标注,批量工具共享)。A(新增)/ M(修改)/ D(删除)徽标。ctx/del/add 行带对齐行号。git(未引用 stash/commit-tree 对象,经 git diff-tree/git show 只读访问)与 copy(快照目录 + manifest),按记录分发;混合 provider 配对拒绝(响亮报错)。.git/.dsh);git provider 只用只读原语,并要求会话 cwd 即仓库根。↩ Undo this restore(面板按钮、/rollback --undo、POST /api/rollback-undo)即可回退:被覆盖文件回到恢复前内容、恢复新建的文件被移除("绝不删除"的唯一例外);仅进程内、无 redo;恢复后被改动的文件跳过不动。(HEAD) 前缀(如 (HEAD) #bbbbbbbb 20:26 · edit b.txt)。HEAD 恒指当前快照(全局最新节点):选择版本、切换分支过滤都不会移动它,刷新时间线后自动移到新快照。git gc 回收(或重克隆丢失)的 git 检查点标 ⚠ degraded,默认选择自动跳过;时间线显示 "N checkpoint(s) degraded" 提示条;diff/回滚报错精确点名死节点。绝不删除任何记录;剪枝记录、缺失记录/文件保持现有明确报错。/diff --trace:把会话日志(session.jsonl.zstd)里的每个工具调用当作时间节点(trace:<seq>),选中任意两节点即"选中区间"——由 write/edit/str_replace_editor 参数重放内容,逐文件逐行 diff(复用同一 LCS 引擎与面板)。无需任何快照生产者:rewind 缺席、快照被配额逐出或被 gc 回收、甚至装插件之前的历史会话,都能回答"这次对话改了哪些文件"。bash/pwsh 等任意命令的修改不可见(重放偏差以 note 诚实标注,绝不静默);数据源优先 sessionQuery.readSession,zstd 帧直读为最后兜底(Node ≥ 23.5)。以"AI 代理改了我的工作区"为场景,与常见方案对比(事实以各项目官方文档为准):
| 工具 | 快照粒度 | 任意两节点 diff | 恢复/回滚 | 与 AI 会话的关联 |
|---|---|---|---|---|
| dsh-checkpoint-diff(本插件) | 每次变更型工具调用前 | ✅ 任意两节点逐文件逐行(GUI 面板 / /diff / API;意图标签、目录树、变更块跳转) | 预览优先 → 应用;绝不删除;单次撤销;整节点或单文件 | 会话内 + 跨会话项目级(fork 血缘、分支) |
| dsh-checkpoint-rewind(上游生产者) | 每次变更型工具调用前(0.5.0 起 + 每回合/定时/手动) | ✅ 设置页两两对比(0.5.0 起:文件变更集 + 配置行级 diff;无工作区文件逐行 diff) | /rewind 预览 → 恢复 → fork(守护检查点;0.5.0 起 seed-replay 会话回退) | 单会话 |
| dsh-turn-rewind | 每条用户消息(更粗) | ❌ 无(changeLedger 服务,未提供可视化 diff) | 对话 + 工作区回退;Web 恢复对话框 | 单会话 |
| dsh-snapshot | 每次 write/edit/删除前(目标文件内容) | ❌ 无行级 diff | 按"对话"整体撤回(可再撤回) | 单会话(项目级配额) |
Claude Code 原生 checkpointing + /rewind | 每对话回合(自动) | 文档未见节点间 diff 视图(以官方文档为准) | /rewind 恢复文件(git tracked) | Claude Code 会话内 |
git 基线(git diff/restore,GitLens 等) | 每次人工 commit | ✅ 任意两 commit 逐行(生态成熟) | git restore/checkout;无预览规划、无撤销保护 | 无(纯仓库) |
| IDE 本地历史(JetBrains Local History / VS Code Timeline) | 每次编辑/保存(逐文件) | 单文件修订级 | 恢复单文件任意修订 | 无 |
| 系统级快照(Time Machine / Windows 文件历史) | 每小时/每天 | ❌ 无逐行 diff | 整文件/目录恢复 | 无 |
注:DSH 生态另有 dsh-message-timeline、dsh-session-timeline、dsh-chat-timeline、dsh-undo-savepoint(DSH 配置域)等时间线/快照类插件;本表聚焦"diff 可视化 + 回滚"维度。
生态位立场(2026-08-17 核实):上游 rewind 0.5.0 已自带设置页时间线与两两对比(文件变更集 + 配置 diff;经读源码核实无工作区文件逐行 diff)。本插件不与生产者比拼"有没有 diff",而是坚持只读消费 + 分析层定位——意图标签、跨会话 fork 血缘、非 git 工作区(copy)、预览回滚 + 单次撤销、/diff 命令与 HTTP API——并自 0.5.0 起提供轨迹重放(Trace):无需任何快照生产者即可从会话日志重放逐行 diff,rewind 在场时继续消费其快照、缺席时独立工作,历史会话开箱即用。生态位评估、兼容性事实(rewind 0.5.0 域升 v2)与差异化路线见 docs/competitive-analysis.md 与 docs/decoupling-design.md。
[!IMPORTANT] 先装上游,再装本插件。 dsh-checkpoint-rewind 是快照生产者——检查点(快照)由它产生;本插件是只读消费端,本身不产生任何快照。只装
dsh-checkpoint-diff而漏掉上游,时间线是空的:Diff 按钮、/diff、回滚都没有数据(只有 Trace (session log) 范围可用,见特性)。漏装了请补装上游并重启 harness。
dsh plugin --profile web add dsh-checkpoint-rewind # ⚠️ 上游快照生产者——必须先装
dsh plugin --profile web add dsh-checkpoint-diff # 本插件(消费端)
两个都是 bundle 插件:dsh plugin add 把它们写进 profile 的 dsh.profile.bundles,各自的 cordis.patch.yml 插入插件行。host 侧变更需重启 harness;浏览器 bundle 以 no-cache 直出,客户端修复刷新页面即可。
bundle 层顺序必须是 rewind 在 diff 之前(diff 插件复用 rewind 打开的 checkpoints 域)。
remove/add会按依赖对象序重排,操作后请核对dsh.profile.bundles。
会话头部(标题右侧动作区)出现 Diff 按钮,点击打开浮层面板:
readTitle);sessionQuery.readTitle,可选服务;不可用时回退为截断的会话短 id 如 session-1641…,完整文本悬停可见);(from.seq, to.seq],与 /diff --trace 一致);左键单击工具 span = 回溯锁定:区间收敛为 "(前一工具调用边界, 该边界]"——直接回答"这一个操作改了什么";再次单击同一 span 强制刷新摘要;非工具 span(消息/命令)回退为选中其最近边界节点。单击空白或 Esc 清除选区、右键菜单提供"查看区间文件差异 / 清除选区";区间内没有工具调用时内联提示且不请求后端。from/to 下拉在时间线下方,作为键盘/精确寻址入口与时间线双向同步;#a1b2c3d4 14:02 · edit README.md);项目范围下选项前缀归属会话短 id(如 [sess-par]);A 新增 / M 修改 / D 删除 徽标,颜色随主题 token);(HEAD) 大写前缀(如 (HEAD) #bbbbbbbb 20:26 · edit b.txt)。HEAD 永远指当前快照(全局最新节点):选择版本、切换分支过滤都不会移动它——刷新时间线后它自动移到新快照;git gc 回收或重克隆丢失)时下拉选项标注 ⚠ degraded:默认选择自动跳过降级节点、时间线显示"N checkpoint(s) degraded"提示条,diff/回滚报错会精确指出哪个节点缺失(如 checkpoint #9312717a (to side) is missing from this repository (bad object …));插件绝不删除任何记录或数据——换用较新节点,或执行 rewind 的 /rewind clear 重置时间线;↩ 按钮可只恢复该文件)→ 预览恢复(dry-run 计划:将恢复/不变/跳过的文件 + 节点之后新建将保留的文件)→ 应用恢复;计划/结果/撤销状态都渲染在卡片内,不再占用左侧文件清单顶部;🔍 文件 品牌色 + 下划线):点击后右侧 diff 区覆盖显示 Restore preview: current workspace → 快照 差异;预览激活时工具栏 from/to 下拉切换为只读的"当前工作区 → 目标节点"(from 显示 (current workspace))。预览与节点对比互相独立:在 from/to 选择其它版本不会清空预览,改恢复目标则自动按新目标重载预览;点击左侧文件行退出预览回到普通 from/to diff;⤷ fork 标记;血缘不完整时显示"更早历史不可见"提示;/diff 列出本会话本工作区的时间线(最近 listLimit 条)
/diff <from> <to> 打印两节点间的变更文件清单 + 逐行 diff
/diff --project 列出项目时间线(全部会话 + 分支头部)
/diff --project <from> <to> 跨会话两节点间的 diff
/diff --trace 列出本会话的轨迹时间线(会话日志重放;无需快照生产者)
/diff --trace <from> <to> 区间内变更文件清单 + 逐行 diff(trace:<seq> / 裸 seq / latest)
/rollback [--project] [--dry-run] <node> [<path>...]
从时间节点恢复工作区文件(单文件或整节点)
/rollback --undo 撤销最近一次恢复(单次)
<from>/<to> 支持检查点 id 前缀或 latest。示例:/diff a1b2c3d4 latest。项目范围下前缀歧义时优先本会话记录。
/rollback 恢复节点的全部文件,或只恢复给出的路径;latest 也是合法节点。--dry-run 只打印计划不写盘(would restore N file(s), M unchanged, K skipped + 将保留的遗留文件);--project 可寻址共享同一工作区的其它会话节点。回滚绝不删除文件——只在原位覆盖写。/rollback --undo 撤销最近一次恢复(本进程内):被覆盖文件回到恢复前内容、恢复新建的文件被删除、之后被改动的文件跳过不动(全部跳过 → 报错)。
webServer 前缀路由 /checkpoint-diff/api/*(同源 JSON)。读端点只接受 GET 并可带 scope=project 参数跨会话寻址;rollback 与 rollback-undo 是 POST 端点(唯二写端点,且只写会话工作区):
| 端点 | 方法 | 参数/请求体 | 返回 |
|---|---|---|---|
/api/timeline | GET | session, scope? | {ok, records[]} 时间线(旧→新);scope=project 附加 branches[] 与 markers[] |
/api/session-title | GET | session | {ok, id, title?} — 会话标题(sessionQuery.readTitle;无标题/服务缺席时只回 id) |
/api/summary | GET | session, from, to, scope? | {ok, from, to, files[{path,status}], totalFiles, truncated} |
/api/file-diff | GET | session, from, to, path, scope? | {ok, ops[{type:'ctx'|'del'|'add', text, a?, b?}], truncated, binary} |
/api/preview-diff | GET | session, target, path, scope? | {ok, path, ops[], truncated, binary, present} — 当前工作区 → 目标快照的预览 diff(只读) |
/api/rollback | POST | JSON {session, target, scope?, paths?, dryRun?} | {ok, dryRun, scope, target, files[{rel,action,reason?,mode?}], restored, unchanged, skipped, leftovers, notes} |
/api/rollback-undo | POST | JSON {session} | {ok, target, time, restored, removed, skipped[]} — 撤销最近一次恢复 |
/api/trace-timeline | GET | session | {ok, records[], spans[], turnBoundaries[]} — 轨迹时间线(会话日志重放,节点 id = trace:<seq>;spans/turnBoundaries 为面板三泳道时间线的绘制数据;含 source 与读取失败时的 error 文案) |
/api/trace-summary | GET | session, from, to | {ok, from, to, files[{path,status}], totalFiles, truncated, notes[]} — 区间变更清单(重放;notes 报告重放偏差) |
/api/trace-file-diff | GET | session, from, to, path | {ok, path, ops[], truncated, binary, notes[]} — 区间内单文件逐行 diff(重放内容) |
/api/rollback:target 为 id 前缀或 latest;paths 限定只恢复这些文件(省略 = 整节点);dryRun: true 只规划不写盘(此时 restored = 将恢复数)。files[].action 为 restore | unchanged | skip;leftovers 列出节点之后新建、被保留(绝不删除)的文件。
/api/preview-diff:diff 方向为当前 → 快照(del = 恢复会删除的当前行,add = 会加回来的快照行);present 为 both 或 workspace-missing(工作区尚无该文件)。
/api/rollback-undo:restored = 写回恢复前内容的文件数,removed = 被删除的恢复新建文件数("绝不删除"的唯一例外),skipped = 恢复后被改动而保留的文件(全部跳过 → 409)。撤销状态只存进程内存——重启 harness 即清空(此后 404 nothing to undo)。
失败返回 {ok:false, error}(400 参数/跨 provider/非法 scope/不安全路径、404 未知会话/文件不在节点/未知端点、405 方法不允许、413 请求体过大、500 存储或 git 错误)。
我们承诺的公开契约(消费契约 + 回滚安全契约):docs/contract.md。
storageDomain 域 checkpoints(与 rewind 同 spec 重声明,见 lib/domain.mjs;域 spec 未从 rewind 包导出)。双版本:rewind 0.5.0 用域 v2(kind/config 必填、无 forkSeq)、0.4.0 用域 v1——本插件按 v2 打开、介质为 v1 时自动回退 v1,schema 为容错超集(新旧记录都能读)。优先复用已打开的域(get),否则自开(open 的 reserved 互斥 + 回退轮询)。(sessionId, cwd) 归属。scope=session(默认)只取当前会话;scope=project 按 workspaceKey 合并全部会话,并沿 /rewind fork 血缘(sessionQuery.traceSession,可选服务,缺席时退化为扁平合并、无分支标记)组织分支;fork 锚点 v1 用 forkSeq、v2(rewind 0.5.0)用子会话创建时间回推的父侧最后记录。tool/call 事件反查(只读):name 与 triggerTool 精确匹配优先;fs/*-intent 触发取本步第一个变更型工具;否则取本步首个调用;日志缺失回退 triggerTool 原文(lib/labels.mjs)。live 会话直接读 session.events;冷会话经 sessionQuery.readSession 按需读取(都失败软降级)。git diff-tree -r -z --name-status(清单)+ git show <ref>:<path>(内容),ref 按 40/64-hex 校验后入参;只读原语,绝不写 git。快照只覆盖已跟踪文件(git stash create 语义)——新建/未跟踪文件不会进入快照;想让它出现在时间线与 diff 里,先 git add <path> 纳入索引即可(无需提交)。$DSH_HOME,缺失时 ~/.dsh)下 dsh-checkpoint-rewind/<workspaceKeyHash16>/<uuid>/(manifest.json + 文件),内容比较(manifest 哈希或字节)判 M。/diff <from> <to> 呈现 from 快照 → to 快照的差异,to 快照不含 to 之后的变更。leftovers)。git provider 要求会话 cwd 即仓库根(快照树路径是仓库根相对),否则响亮拒绝。最近一次应用可用 /rollback --undo 撤销一次(进程内)。pnpm install # 依赖(zod/esbuild/jsdom/react,测试自足)
pnpm test # 单测(diff 引擎 / 时间线 / jsdom 面板冒烟)
pnpm test:integration # 组装式 headless 集成(真 rewind + 真存储域)
pnpm build:client # 打包浏览器半 → lib/client.js(+ .map)
约定与设计见 CONTRIBUTING.md 与 ARCHITECTURE.md。集成测试消费本机 harness 部署(rc.5 包未发布到 npm;见 scripts/link-profile-deps.mjs)。
scope=project 目前每次请求全表扫描;宿主事件词汇覆盖 checkpoint/* 后可经 sessionProjections 按 workspaceKey 建索引。装了本插件,但 Diff 按钮 / /diff 没有任何时间节点?
大概率是漏装了上游插件 dsh-checkpoint-rewind(快照生产者)。本插件不产生快照,只读消费上游留下的检查点——上游缺席时检查点时间线为空(只有 Trace (session log) 范围可用)。请补装上游并重启 harness;同时确认 profile 里 bundle 顺序是 rewind 在 diff 之前(见安装)。
我改了工作区文件,但 checkpoint 却提示 "nothing new was captured"?
两种常见原因:① 改的是未跟踪文件——git 快照只覆盖已跟踪文件(见数据契约),git add <path> 纳入索引后再建检查点即可;② 自动快照刚捕获过同一状态——去重消息会附注"latest checkpoint (auto, seq …) already records this exact workspace state",此时节点其实已经存在,直接去时间线对比即可。
本插件构建于 dsh-checkpoint-rewind(作者 PerryLink)之上——它是检查点生产者,本插件只读消费其 checkpoints 存储域与快照目录布局。并非 fork,也不共享代码:两者仅通过存储契约集成。第三方声明见 THIRD_PARTY_NOTICES.md。
Apache-2.0(与 dsh-checkpoint-rewind 兼容)。第三方声明见 THIRD_PARTY_NOTICES.md。
FAQs
File-diff visualization between checkpoint time nodes for DeepSeek Harness: a read-only timeline + per-file line diff over the dsh-checkpoint-rewind checkpoints storage domain, with preview-first rollback (restore workspace files from any time node, singl
The npm package dsh-checkpoint-diff receives a total of 123 weekly downloads. As such, dsh-checkpoint-diff popularity was classified as not popular.
We found that dsh-checkpoint-diff demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
Cloudflare is acquiring Deno’s team, which will provide another year of bug fixes and security updates before ending support for the runtime.

Security News
Anthropic’s free OSS Scanner uses Mythos and other Claude models to find open source vulnerabilities and send maintainers reports with proposed fixes.

Security News
On Front Lines’ Early Adopters: CISO podcast, Andrew Becherer shares lessons from Datadog, weighs the long-term costs of AI-built tools, and explains how founders can actually gain a CISO’s trust.