12. /btw 与 /rewind 功能对比
March 25, 2026 · View on GitHub
对"旁问"与"回退"两个高级会话管理命令的源码级实现逐工具对比。这两个命令解决的是同一个核心问题:如何在长会话中保持上下文的纯净性和可逆性。
一、/btw(旁问/侧边问题)
在不打断主对话流的情况下,快速问一个无关问题。结果不会污染主会话上下文。
支持情况总览
| Agent | 是否支持 | 命令名 | 备注 |
|---|---|---|---|
| Claude Code | ✓ | /btw | 本地 JSX 实现,独立 prompt ID(Fp_=/^\/btw\b/gi) |
| Gemini CLI | ✗ | — | 无 /btw 命令(仓库搜索 0 匹配,命令目录无 btwCommand) |
| Qwen Code | ✓ | /btw | Qwen 自行添加(btwCommand.ts,非继承 Gemini CLI) |
| Copilot CLI | ✗(社区请求中) | — | Issue: "/btw command for quick ephemeral side questions" |
| Aider | ✗ | — | 无类似功能 |
| Goose | ✗ | — | 无类似功能 |
| Kimi CLI | ✗ | — | 无类似功能 |
| Codex CLI | ✗ | — | 无类似功能 |
核心设计理念
/btw 解决的是上下文污染问题。在长会话中,用户经常需要临时查询一些与当前任务无关的信息(比如某个 API 的用法、某个配置项的含义)。如果直接在主对话中提问,这些无关内容会:
- 占用上下文窗口 — 加速触发压缩阈值
- 干扰模型理解 — 模型可能误以为旁问内容与主任务相关
- 污染会话历史 — 后续
/compact时需要额外处理这些噪音
/btw 通过创建一个完全独立的临时 prompt来规避以上所有问题。
实现架构对比
Claude Code(最完整的实现)
Claude Code 的 /btw 实现采用本地 JSX 渲染:
核心流程:
1. 解析 /btw 后的文本作为独立问题
2. 创建 side prompt(独立 ID,makeBtwPromptId + timestamp)
3. 独立上下文中执行 LLM 调用
4. 渲染结果到终端
5. 结果标记为 ephemeral,不进入主会话 messages 数组
与 Gemini CLI 的区别:
- Claude Code 使用 JSX 组件渲染回答,视觉上与主对话有明显区分
- 支持更丰富的输出格式(代码块、表格等在侧边回答中也能正常渲染)
Qwen Code(独立实现)
重要修正: Qwen Code 的
/btw不是继承自 Gemini CLI——Gemini CLI 根本没有 /btw。这是 Qwen 团队自行添加的功能。
源码位置:packages/cli/src/ui/commands/btwCommand.ts
实现逻辑与 Claude Code 类似:
- 独立的 prompt ID(基于 session ID + 时间戳)
- 不携带主会话历史
- 模型调用走 Qwen 自己的 API 通道
/btw 的限制
| 限制项 | 说明 |
|---|---|
| 无工具调用 | /btw 中的回答不能调用文件读写、搜索等工具 |
| 无上下文 | 侧边问题看不到主会话的任何内容 |
| 无持久化 | 回答不保存,关闭终端即丢失 |
| 单轮问答 | 不支持在 /btw 内多轮追问 |
二、/rewind(回退/检查点)
将代码和/或对话回退到之前的某个状态。是长会话中"后悔药"的核心实现。
支持情况总览
| Agent | 是否支持 | 命令名 | 回退范围 | 备注 |
|---|---|---|---|---|
| Claude Code | ✓ | /rewind(别名 /checkpoint) | 代码 + 对话 | Esc 键也可触发 |
| Gemini CLI | ✓ | /rewind | 代码 / 对话 / 两者皆可 | RewindViewer 组件,3 种选项 |
| Qwen Code | /restore | 无 /rewind | 有 /restore 恢复检查点 | 未继承 Gemini 的 /rewind 命令 |
| Aider | 部分 | /undo | 仅代码(Git 提交) | 只回退 Aider 自己的提交 |
| Kimi CLI | ✗ | — | — | 有实验性 D-Mail 时间旅行(okabe agent) |
| Goose | ✗ | — | — | 无类似功能 |
| Copilot CLI | ✗ | — | — | 无类似功能 |
| Codex CLI | ✗ | — | — | 无类似功能 |
核心设计差异
回退功能的复杂度远超旁问。它需要解决三个正交维度的问题:
- 代码回退 — 文件系统变更如何撤销?
- 对话回退 — 会话历史如何截断?
- 一致性 — 代码状态与对话状态如何保持同步?
不同工具在这三个维度上做出了截然不同的选择。
实现架构对比
Gemini CLI(最完整的实现)
源码关键组件:custom_dialog + RewindViewer
检查点存储机制:
- 检查点以 Git 快照形式存储在
~/.gemini/history/<hash>目录下 - 每次工具调用完成后自动创建检查点
- 存储内容包括:文件变更快照 + 对话消息索引
三种回退选项:
| 选项 | 含义 | 行为 |
|---|---|---|
| Both(代码+对话) | 完全回退 | 恢复文件系统 + 截断会话历史至检查点 |
| Conversation only(仅对话) | 保留代码变更 | 只截断会话历史,文件保持当前状态 |
| Code only(仅代码) | 保留对话 | 只恢复文件系统,会话历史保持不变 |
UI 交互流程:
1. 用户输入 /rewind
2. 显示 RewindViewer 组件
3. 列出所有可用检查点(附带文件变更统计)
4. 用户选择目标检查点
5. 用户选择回退范围(3 种选项之一)
6. 执行回退
7. 显示回退结果摘要
文件变更统计展示示例:
检查点 #3 (2 分钟前)
修改: src/index.ts (+15, -3)
新增: src/utils.ts (+42)
删除: src/old.ts (-28)
Claude Code
Claude Code 的 /rewind 实现(别名 /checkpoint)有独特设计:
触发方式:
- 命令触发:
/rewind - 快捷键触发:
Esc键(在 agent 执行过程中按下)
回退机制:
- 文件系统回退:基于 worktree 隔离的快照恢复
- 对话回退:截断 messages 数组至检查点对应的消息索引
- 两者默认同时回退(代码 + 对话)
与 Gemini CLI 的区别:
- Claude Code 不提供"仅回退代码"或"仅回退对话"的细粒度选项
- 默认行为是同时回退两者,保持严格的一致性
- Esc 键触发是 Claude Code 独有的交互模式,适用于"发现 agent 走偏了"的场景
Aider(/undo — 最简实现)
Aider 的 /undo 采用完全不同的哲学:只管 Git,不管对话。
核心实现逻辑:
# 伪代码,基于源码分析
def cmd_undo():
# 1. 获取最近一次提交
last_commit = repo.head.commit
# 2. 检查是否是 aider 的提交
if last_commit.hexsha not in aider_commit_hashes:
# 拒绝撤销非 aider 的提交
error("只能撤销 aider 创建的提交")
return
# 3. 检查是否已推送
if is_pushed(last_commit):
error("拒绝撤销已推送的提交")
return
# 4. 执行 git reset
repo.git.reset("--hard", "HEAD~1")
关键安全检查:
| 检查项 | 说明 |
|---|---|
aider_commit_hashes 集合 | 只允许撤销 aider 自己创建的提交 |
| 推送检查 | 已推送到远程的提交不允许撤销 |
| 单步撤销 | 每次只撤销一个提交(HEAD~1) |
限制:
- 不回退对话历史(
/undo后对话中仍保留已撤销的内容) - 只能撤销最近一次 aider 提交,不能跳跃回退
- 如果用户手动做了提交,aider 的
/undo会停止(因为 HEAD 不在aider_commit_hashes中)
Kimi CLI(实验性时间旅行)
Kimi CLI 没有标准的 /rewind 命令,但在 okabe agent 中有一个实验性的 D-Mail 功能:
- 灵感来自动画《命运石之门》中的 D-Mail 概念
- 属于实验性质,非正式功能
- 不建议在生产环境中使用
三、综合对比表
/btw 对比
| 维度 | Claude Code | Qwen Code |
|---|---|---|
| 独立上下文 | ✓ | ✓ |
| 工具调用 | ✗ | ✗ |
| 多轮追问 | ✗ | ✗ |
| 视觉区分 | JSX 组件渲染 | 终端文本 |
| ID 生成 | makeBtwPromptId + timestamp | session ID + timestamp |
| 持久化 | ✗(ephemeral) | ✗(ephemeral) |
注: Gemini CLI 没有 /btw 命令(仓库搜索 0 匹配),已从对比表移除。
/rewind 对比
| 维度 | Claude Code | Gemini CLI | Qwen Code | Aider |
|---|---|---|---|---|
| 命令名 | /rewind(/checkpoint) | /rewind | /restore(无 /rewind) | /undo |
| 代码回退 | ✓ | ✓ | ✓(通过 /restore) | ✓(仅 Git) |
| 对话回退 | ✓ | ✓ | ✓(通过 /restore) | ✗ |
| 回退粒度 | 两者同时 | 3 种选项可选 | 检查点恢复 | 仅代码 |
| 存储方式 | worktree 快照 | Git 快照(~/.gemini/history/) | 继承 Gemini 检查点 | Git 提交历史 |
| 安全检查 | ✓ | ✓(文件变更预览) | ✓ | ✓(仅 aider 提交 + 推送检查) |
| 快捷键触发 | Esc | ✗ | ✗ | ✗ |
| 跳跃回退 | ✓(选择检查点) | ✓(选择检查点) | ✓(/restore) | ✗(仅 HEAD~1) |
| UI 组件 | 终端内置 | RewindViewer | restoreCommand | 纯命令行输出 |
四、设计洞察
/btw 的优雅之处
/btw 是一个看似简单但设计精妙的功能。它的核心洞察是:
在有限的上下文窗口中,每一条消息都有成本。
当上下文窗口接近容量上限时(尤其是 Claude Code 在约 95% 时才触发压缩),每一条无关消息都会加速压缩的到来。而压缩必然伴随信息丢失。/btw 通过将无关问答完全隔离,从根本上消除了这个成本。
目前只有 2 个工具实现了 /btw(Claude Code 和 Qwen Code)。Gemini CLI 虽然是 Qwen Code 的上游,但没有 /btw——这是 Qwen Code 自行添加的功能。大多数工具还没有意识到上下文污染是一个值得专门解决的问题。随着会话长度增加和上下文管理变得更加关键,预计更多工具会采纳类似设计。
/rewind 的基础设施需求
/rewind 的实现复杂度远高于 /btw,因为它需要:
- 快照基础设施 — 必须有可靠的文件系统状态保存机制
- 消息索引 — 必须能精确定位对话历史中的任意位置
- 一致性保证 — 代码状态与对话状态必须能独立或联合回退
- UI 展示 — 需要向用户清晰展示每个检查点的变更内容
Gemini CLI 选择了基于 Git 的快照方案(~/.gemini/history/<hash>),这是最自然的选择——毕竟代码项目本身就是用 Git 管理的。但这也带来了额外的存储开销。
Aider /undo 的取舍
Aider 的 /undo 是一个典型的简单但有效的设计:
- 优点: 零额外基础设施(复用 Git 本身),实现简洁,安全检查到位
- 缺点: 不能回退对话,不能跳跃回退,不能回退非 aider 的变更
这种设计适合 Aider 的使用场景:Aider 的每次代码修改都对应一个 Git 提交,所以 /undo 就是 git reset --hard HEAD~1 加上安全检查。但对于不以 Git 提交为最小操作单元的工具(如 Gemini CLI 和 Claude Code),这种方案就不够用了。
两个命令的协同关系
/btw 和 /rewind 解决的是同一枚硬币的两面:
| 问题 | /btw 的解法 | /rewind 的解法 |
|---|---|---|
| 上下文被污染了 | 预防: 旁问不进入上下文 | 治疗: 回退到污染前的状态 |
| Agent 走偏了 | 不适用 | 回退代码和对话 |
| 想快速查个东西 | 独立的临时问答 | 不适用 |
| 代码改坏了 | 不适用 | 恢复文件系统快照 |
理想的工具应该同时提供两者:用 /btw 预防上下文污染,用 /rewind 在出错时回退。目前只有 Claude Code 同时支持 /btw 和 /rewind。Qwen Code 有 /btw 和 /restore 但无 /rewind。Gemini CLI 有 /rewind 但无 /btw。
五、未来趋势
- 更多工具将引入 /btw — 上下文管理是所有 AI 编程工具的核心挑战,
/btw的零成本侧边问答是一个被验证有效的方案 - /rewind 的粒度将更细 — 未来可能支持函数级别的回退,而不仅仅是文件级别
- 自动检查点 — 目前大部分工具的检查点创建是自动的(每次工具调用后),但检查点的清理策略还不成熟
- 跨会话回退 — 当前所有
/rewind实现都限制在单次会话内,跨会话的回退能力是下一个前沿方向