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/btwQwen 自行添加btwCommand.ts,非继承 Gemini CLI)
Copilot CLI✗(社区请求中)Issue: "/btw command for quick ephemeral side questions"
Aider无类似功能
Goose无类似功能
Kimi CLI无类似功能
Codex CLI无类似功能

核心设计理念

/btw 解决的是上下文污染问题。在长会话中,用户经常需要临时查询一些与当前任务无关的信息(比如某个 API 的用法、某个配置项的含义)。如果直接在主对话中提问,这些无关内容会:

  1. 占用上下文窗口 — 加速触发压缩阈值
  2. 干扰模型理解 — 模型可能误以为旁问内容与主任务相关
  3. 污染会话历史 — 后续 /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无类似功能

核心设计差异

回退功能的复杂度远超旁问。它需要解决三个正交维度的问题:

  1. 代码回退 — 文件系统变更如何撤销?
  2. 对话回退 — 会话历史如何截断?
  3. 一致性 — 代码状态与对话状态如何保持同步?

不同工具在这三个维度上做出了截然不同的选择。

实现架构对比

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 CodeQwen Code
独立上下文
工具调用
多轮追问
视觉区分JSX 组件渲染终端文本
ID 生成makeBtwPromptId + timestampsession ID + timestamp
持久化✗(ephemeral)✗(ephemeral)

注: Gemini CLI 没有 /btw 命令(仓库搜索 0 匹配),已从对比表移除。

/rewind 对比

维度Claude CodeGemini CLIQwen CodeAider
命令名/rewind/checkpoint/rewind/restore(无 /rewind)/undo
代码回退✓(通过 /restore)✓(仅 Git)
对话回退✓(通过 /restore)
回退粒度两者同时3 种选项可选检查点恢复仅代码
存储方式worktree 快照Git 快照(~/.gemini/history/继承 Gemini 检查点Git 提交历史
安全检查✓(文件变更预览)✓(仅 aider 提交 + 推送检查)
快捷键触发Esc
跳跃回退✓(选择检查点)✓(选择检查点)✓(/restore)✗(仅 HEAD~1)
UI 组件终端内置RewindViewerrestoreCommand纯命令行输出

四、设计洞察

/btw 的优雅之处

/btw 是一个看似简单但设计精妙的功能。它的核心洞察是:

在有限的上下文窗口中,每一条消息都有成本。

当上下文窗口接近容量上限时(尤其是 Claude Code 在约 95% 时才触发压缩),每一条无关消息都会加速压缩的到来。而压缩必然伴随信息丢失。/btw 通过将无关问答完全隔离,从根本上消除了这个成本。

目前只有 2 个工具实现了 /btw(Claude Code 和 Qwen Code)。Gemini CLI 虽然是 Qwen Code 的上游,但没有 /btw——这是 Qwen Code 自行添加的功能。大多数工具还没有意识到上下文污染是一个值得专门解决的问题。随着会话长度增加和上下文管理变得更加关键,预计更多工具会采纳类似设计。

/rewind 的基础设施需求

/rewind 的实现复杂度远高于 /btw,因为它需要:

  1. 快照基础设施 — 必须有可靠的文件系统状态保存机制
  2. 消息索引 — 必须能精确定位对话历史中的任意位置
  3. 一致性保证 — 代码状态与对话状态必须能独立或联合回退
  4. 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。


五、未来趋势

  1. 更多工具将引入 /btw — 上下文管理是所有 AI 编程工具的核心挑战,/btw 的零成本侧边问答是一个被验证有效的方案
  2. /rewind 的粒度将更细 — 未来可能支持函数级别的回退,而不仅仅是文件级别
  3. 自动检查点 — 目前大部分工具的检查点创建是自动的(每次工具调用后),但检查点的清理策略还不成熟
  4. 跨会话回退 — 当前所有 /rewind 实现都限制在单次会话内,跨会话的回退能力是下一个前沿方向