第 08 章

Checkpoints

快照与回退——让探索和迭代变得安全可控

大胆尝试,随时回退 — 不再害怕改坏代码

不敢大胆试

你有没有发现,想试一个新方案但怕改坏了回不去?

想试新方案

你想给 API 加个 Redis 缓存层。改了 8 个文件后,发现这个方案跟现有架构不兼容。撤回 8 个文件的修改,比重新写还痛苦。

重构到一半

把认证模块从 Session 迁移到 JWT。改到一半发现 OAuth 集成被弄坏了。代码处于半成品状态,前进也不是,后退也不是。

想比较方案

两种实现思路都想试试。但试完一个想试另一个时,代码已经被改得面目全非,回不到起点了。

Checkpoints 就是为这个设计的:每次改动前自动保存状态快照。随时可以回退到任意历史节点,零成本撤销。大胆试,不怕错。

三个概念

Checkpoint、Rewind、Branch Point

Checkpoint是当前对话状态的完整快照,包含所有消息、文件修改、工具使用历史和会话上下文。

说白了,它就是一个"游戏存档"——你玩到某个关键节点,存一下。后面走错了路,读档回去就行。这个比喻只是为了帮你建立直观感受。实际上,Checkpoint 保存的是对话历史和文件状态的元数据,而不是文件内容的完整拷贝——恢复时它会重放操作历史来还原状态。

概念说明
Checkpoint保存消息、文件和上下文的对话快照
Rewind回到之前的 checkpoint,丢弃之后的更改
Branch Point从同一个 checkpoint 出发,探索多个方案
自动机制:每次用户输入都会自动创建 checkpoint,无需手动操作。你只管做事,该存的时候它会自动存。

如何回退

两种方式打开 Checkpoint 浏览器

快捷键

按两次 Esc(Esc + Esc)打开 checkpoint 浏览界面。

Slash Command

$ /rewind
# 或别名
$ /checkpoint

每个 Checkpoint 显示什么

打开 checkpoint 浏览器后,你会看到每个快照包含四项信息:创建时间、被修改的文件、对话中的消息数量、使用过的工具。这些信息帮你快速判断哪个节点值得回退。

Rewind 的 5 个选项

选项效果
恢复代码和对话文件和消息都恢复到该 checkpoint
恢复对话只回退消息,保留当前代码
恢复代码只回退文件修改,保留完整对话
从这里开始总结把后续对话压缩成摘要,原始消息仍保留在记录中
算了取消,返回当前状态

总结压缩

长对话的"减肥"工具——不丢结论,只减噪音

当你经过 20 多条消息的调试和探索后,对话已经很长了。这时你可以用"从这里开始总结"来压缩对话——它会把从该 checkpoint 到现在的所有消息压缩成一段 AI 生成的摘要。

# 场景:长调试会话后压缩上下文

用户: [经过 20 多条消息的调试和探索]

[按 Esc+Esc,选择较早的 checkpoint,选择"从这里开始总结"]
[可选:提供指令,如"重点保留我们尝试过什么,以及什么有效"]

Claude: [生成从该点开始的对话总结]
[原始消息仍保留在记录里,不会丢失]
[总结替换当前可见对话,减少上下文窗口占用]

用户: "现在继续推进那个有效的方案"

三个要点

  • 原始消息不丢失——它们仍在记录中,只是不可见了
  • 可以指定摘要重点——告诉 Claude 聚焦什么主题
  • 释放上下文窗口——长对话不再挤占 AI 的工作记忆

什么时候用

  • 经过长时间调试,对话已经很长
  • 探索了多个方向,想压缩成结论
  • 回退前想保留之前的发现,而非直接丢弃

分支探索

保存 → 试方案 A → Rewind → 试方案 B → 比较

图:分支探索模式——从同一个 Checkpoint 出发探索两条路径
# 场景:给 API 加缓存层

用户: "我们给 API 加一个缓存层吧"
Claude: 我会为你的 API 端点添加 Redis 缓存……
[在 checkpoint A 处做出修改]

用户: "其实我们先试试内存缓存"
Claude: 我会 rewind 回去,探索另一种方案……
[用户按 Esc+Esc,回退到 checkpoint A]
[在 checkpoint B 处实现内存缓存]

用户: "现在我可以比较两种方案了"
核心模式:从同一个 checkpoint 出发,尝试不同的实现路径。比较完之后选择最佳方案,丢弃其他尝试。

安全重构

当前状态 → checkpoint → 开始重构 → 运行测试 → 失败则 Rewind

图:安全重构循环——每次改动都有 checkpoint 托底
# 场景:重构认证模块

用户: "把认证模块重构成 JWT"
Claude: 我会重构认证模块……
[做出大量修改]

用户: "等等,这把 OAuth 集成弄坏了。我们回去。"
Claude: 我来帮你回退到重构之前……
[用户按 Esc+Esc,选择重构前的 checkpoint]

用户: "这次我们试一个更保守的方案"
Claude: [基于回退后的状态,逐步重构]
安全重构模式:不需要手动 git stash 或创建备份分支。直接开始重构,每一步都有 checkpoint 托底。测试失败了就 Rewind,成本几乎为零。

性能优化

同一起点出发,试 3 种策略,组合后提升 79%

# 起点:API 响应时间 450ms

用户: "我们来优化 API 响应时间"
      [Checkpoint "Baseline" 自动创建]

# --- 第一轮:Redis 缓存 ---
Claude: 我来加数据库查询缓存…… [实现 Redis 缓存]
用户: 运行性能测试
Claude: 结果:280ms(提升 38%)

# --- Rewind 回 Baseline,试第二种 ---
用户: [按 Esc+Esc,选择 Baseline]
用户: 改试数据库查询优化
Claude: [添加索引,优化 N+1 查询]
用户: 运行性能测试
Claude: 结果:180ms(提升 60%)← 最优

# --- Rewind 回 Baseline,试第三种 ---
用户: [按 Esc+Esc,选择 Baseline]
用户: 尝试响应压缩和 CDN
Claude: [实现 gzip + CDN]
用户: 运行性能测试
Claude: 结果:320ms(提升 29%)

# --- 回到最优方案,叠加缓存 ---
用户: 查询优化最好。回到那个版本,再加上 Redis 缓存。
Claude: [在优化查询之上添加 Redis 缓存]
Claude: 结果:95ms(提升 79%)

三种策略对比

策略响应时间提升
Redis 缓存280ms38%
查询优化180ms60%
压缩 + CDN320ms29%
查询优化 + 缓存95ms79%

关键思路

  • 同一起点(Baseline)出发,分别测试 3 种策略

找到最优解后,回到该检查点叠加第二种优化——组合效果远超单独使用任何一种。这种"试 → 比 → 叠加"的模式,只有检查点才能低成本实现。

调试会话

多个假设逐一排除——内存泄漏排查实录

# 起点:应用存在内存泄漏

用户: "应用里有内存泄漏"
      [Checkpoint "Before debugging" 自动创建]

# --- 假设 1:事件监听器 ---
用户: 我觉得问题在事件监听器里
Claude: [修复事件监听器清理逻辑]
用户: 运行内存分析器
Claude: ❌ 仍然在泄漏——不是事件监听器的问题

# --- Rewind,试假设 2 ---
用户: [按 Esc+Esc,选择 "Before debugging"]
用户: 也许是数据库连接的问题?
Claude: [实现连接池修复]
用户: 运行内存分析器
Claude: ❌ 还是在泄漏——也不是连接的问题

# --- Rewind,试假设 3 ---
用户: [按 Esc+Esc,选择 "Before debugging"]
用户: 检查一下有没有循环引用
Claude: [找到并修复缓存中的循环引用]
用户: 运行内存分析器
Claude: ✅ 内存泄漏修复了!

假设驱动的调试模式

  • 提出假设 → 实现修复 → 验证结果
  • 假设失败 → Rewind 回起点 → 换下一个假设
  • 每次回到同一个检查点,确保代码状态干净

为什么检查点关键

传统调试中,每个失败的修复都会污染代码状态——你得手动撤销才能试下一个假设。有了检查点,每次回退都是完整、干净的,不存在"改了 A 又忘了改回 B"的风险。

安全试验

激进改动不怕错——试了不行就回退

# 场景:尝试函数式风格改写

用户: "我们试着把它改写成函数式风格"
      [检查点在提示前自动创建]

Claude: [执行实验性修改——重写核心逻辑为纯函数]
Claude: [移除可变状态,改用不可变数据流]

用户: 运行测试
Claude: ❌ 12 个测试失败,类型推断出了问题

用户: 测试失败了。我们回退吧。
[用户按 Esc+Esc,回退到实验前的检查点]

Claude: 我已经回退这些更改了。我们试另一个方案。
安全试验模式:想试一个激进的想法?直接试。不需要手动备份、不需要 git stash。检查点在改动之前就自动保存了——如果实验失败,一条命令回到原点,什么都没丢。
适用场景:函数式风格改写、新的设计模式引入、依赖升级、不熟悉的库的试水……凡是"不确定能不能成"的改动,都可以先试再说。

何时该回退

这些信号出现时,通常就该考虑 rewind 了

方向变复杂了

当前方案开始变复杂,而且你还没确定方向。这说明你可能走偏了——回退到上一个"干净"状态,换个思路重新来。

测试刚失败

问题大概率就是最近一两步引入的。别在错误的基础上继续改——回退到测试通过的那一步,从那里重新出发。

想比较两种实现

你觉得当前方案可以,但又想试另一种。先记住当前方案的效果,rewind 回去试新方案,最后对比选择。

想要一个干净起点

探索了半天方向不明确。回退到一个已知的"好状态",重新规划路线,比在混乱中继续摸索更高效。

简单原则:当你觉得"这段改动可能不对"的时候,就是回退的最佳时机。越早回退,成本越低。

与 Git 互补

Checkpoints 和 Git 是互补的,不是替代关系

Checkpoints

  • 会话级快照,自动创建
  • 适合快速试错和方案比较
  • 跨会话保留,30 天后自动清理
  • 仅当前用户可见,不共享

Git

  • 代码级版本控制,需手动 commit
  • 适合长期保存和团队协作
  • 永久保留(除非手动删除)
  • 可共享,团队协作基础

推荐用法

  • ✅ 用 Checkpoints 快速试错、比较方案
  • ✅ 找到最佳方案后,提交到 Git
  • ✅ 关键节点手动 commit 到 Git 保存
  • ✅ 长会话用"总结"保持可管理

避免的做法

  • ❌ 只依赖 Checkpoints 保存代码
  • ❌ 指望 Checkpoints 跟踪外部文件变化
  • ❌ 把 Checkpoints 当成 Git commit 的替代品

局限性

Checkpoints 很强,但它不是万能的

不是版本控制系统

Checkpoints 适合会话内的快速回退和方案探索,但它不能替代 Git。需要长期保存、可审计、可共享的改动,仍然应该使用 git commit。

30 天自动清理

旧检查点最多保留 30 天,之后自动清理。如果你有一个月前的探索记录想保留,关键结果必须手动提交到 Git。

不跟踪外部变化

检查点只记录 Claude Code 会话中的操作。你在会话外用编辑器改的文件、用终端跑的命令,检查点无法感知。

仅当前用户可见

检查点是个人会话快照,不能共享给团队成员。团队协作请用 Git,检查点只负责帮你快速试错。

简单原则:检查点负责"探索和试错",Git 负责"落地和保存"。两者互补,不要只用一个。

配置与保留

自动保存、跨会话持久化、可关闭

自动机制

每次用户输入都会自动创建 checkpoint,无需手动操作。你只管做事,该存的时候它会自动存。这些快照会跨会话保留——即使你关掉 Claude Code,下次打开时仍然可以回到之前的节点。

旧 checkpoint 最多保留 30 天,之后自动清理,避免存储无限增长。

可配置项

如果你不需要自动 checkpoint,可以在设置中关闭:

{
  "autoCheckpoint": false
}

默认值是 true。关闭后,Claude Code 不再自动创建快照,你需要手动管理状态。

排错指南

找不到 Checkpoints

症状:按 Esc+Esc 后没有看到任何快照。

检查:确认你的 Claude Code 版本是否支持 checkpoints;检查 autoCheckpoint 设置是否被关闭了;试试重新打开会话。

Rewind 失败

症状:选择 checkpoint 后回退操作失败。

检查:确认选择的是一个有效 checkpoint;查看是否有文件系统或权限限制;试试先单独恢复代码或对话,不要同时恢复两者。

回退太频繁

症状:每次小改动都 rewind,浪费大量时间。

修复:只在关键转折点回退。小修改直接撤销就好,不需要 checkpoint。

改动太多才回退

症状:改了 20 个文件才想起来可以回退,回退代价太大。

修复:养成习惯:每完成一个"可验证的阶段"就确认一下。如果这个阶段结果不对,立刻 rewind。

只依赖 Checkpoints

症状:从来不手动 git commit,全指望 checkpoints 保存代码。

修复:Checkpoints 30 天后自动清理。关键代码必须手动 commit 到 Git。

回退后忘了之前试过什么

症状:rewind 了但忘了之前的方案,又重复探索了一遍。

修复:在 Rewind 时选择"从这里开始总结"——它会压缩后续对话成摘要,保留关键结论但不占空间。

动手练习

设计一个"三段式 Checkpoint"策略

不用真的去改代码,只设计分段策略——每个阶段什么时候打点、验证什么、什么情况下 rewind。

题目:重构用户认证模块(从 Session 迁移到 JWT)。拆成 3 个阶段。
  • 每个阶段的创建时机
  • 每个阶段的验证标准
  • 什么情况下需要 rewind

参考答案

Checkpoint 1

开始前
✅ 原有测试通过

Checkpoint 2

提取接口后
✅ 编译通过

Checkpoint 3

替换实现后
✅ 测试全部通过

阶段目标验证标准Rewind 条件
1 → 2提取 AuthProvider 接口编译通过,无报错编译失败或引入新错误
2 → 3实现 JWTAuthProvider原有测试全部通过任何原有测试失败
3 → 完成添加 JWT 专属测试新旧测试全部通过新测试无法通过
核心原则:每个 checkpoint 对应一个可验证的结果。验证通过就继续,验证失败就 rewind。这样无论重构到哪一步,你都不会"回不去"。

本章回顾

到这里,你已经能

  • 说清 Checkpoint 与 Rewind 的用途
  • 知道触发时机和访问方式
  • 设计分段式 Checkpoint 策略
  • 理解与 Git 的互补关系
  • 掌握分支探索和安全重构两种模式

它和前后章节的关系

  • Hooks — 在 checkpoint 前后自动做质量检查
  • Plugins — 插件工作流中的安全试错
  • Checkpoints — 让探索更安全的快照机制
  • Advanced Features — 规划模式 + checkpoints 的系统化组合
核心结论:Checkpoints 让"先试再说"变得安全。它降低了探索的成本,让你敢于尝试更多方案。但别忘了——关键代码还是要手动 commit 到 Git。

延伸阅读

继续本课程

示例文件 (点击查看完整内容)

08-checkpoints/
└── checkpoint-examples.md

更多实战示例

  • checkpoint-examples.md — 7 个完整工作流示例
  • 数据库迁移(直接迁移 vs 双写模式)
  • UI/UX 迭代(三种布局比较,最终组合方案)
  • API 设计演进(REST vs GraphQL 来回比较)
  • 配置管理(环境变量 vs YAML 配置文件)
  • 测试策略(单元测试 → 集成测试 → E2E 渐进构建)

外部资源

本章源文件

  • 08-checkpoints/README.md — 完整说明文档
  • 08-checkpoints/checkpoint-examples.md — 实战示例集合

加载中…