/btw 一个让 cli 学会“一边干活一边聊天”的神奇命令

122 阅读6分钟

🍕 那个憋屈的瞬间

想象一个场景——

你走进餐厅,刚坐下就点了一份豪华披萨。服务员小哥转身走了,披萨开始在后厨烤。

突然你渴了,想加一杯可乐。你朝服务员招手——

他看了你一眼,说:“先生不好意思,我正在为您烤披萨。等我烤完再来招呼您。”

你:???

这不就是以前用 Claude Code 的真实写照吗?

你让它重构整个项目,代码写到一半,你突然想问:“诶对了,那个依赖包的最新 API 是什么来着?”

然后 Claude 停下来,回答你的问题,再试图继续。但此时它的“上下文窗口”里已经多了一大段不相关的对话,它回来接着写的时候,思路已经跑偏了

这叫“上下文污染”。用久了的人,基本都被坑过


💡 /btw 来了

2026 年 3 月 11 日,Anthropic 团队的 Thariq 在 X 上发了条消息:Claude Code 加了个新命令 /btw

这东西到底是什么?

/btw 就是 “by the way” 的缩写——跟人类聊天时随口说的“顺便说一下”一模一样。

用法超级简单:

# 在主任务运行的同时
/btw retry logic 是做什么的?

你一个回车,答案立刻弹出一个浮层。看完按空格、回车或 Escape 关闭。主任务在后台继续跑,完全不受影响

就像餐厅给你配了一个专门的服务员,随时回答你的随口提问,不影响主菜上桌


🔍 它到底在“背后”做了什么?

要搞懂 /btw 的原理,得先明白 Claude Code 的“上下文窗口”是怎么工作的。

🧠 先理解“上下文污染”

每次你和一个大语言模型对话,模型看到的不仅是你的最新消息——它看到的是整个对话历史

在普通模式里:

你:帮我重构这个 Python 模块
Claude:好的,开始重构...(写了一大堆代码)
你:btw 昨天那个测试文件在哪里?
Claude:在 tests/test_main.py
你:继续重构...

此时 Claude 的上下文里包含了“测试文件在哪里”这段完全无关的对话。它回来接着写代码时,可能就会跑偏,因为你打断它的思路了

而且更糟糕的是:每一个后续的 API 调用,都会重新读取整个对话历史。随着对话变长,每次请求消耗的 token 会越来越多,成本也随之攀升

🪄 /btw 的核心机制

当你输入 /btw 时,Claude Code 不会把这个请求添加到主对话历史中。它会:

  1. 读取当前主会话的提示缓存,理解你已经做了什么事情
  2. 生成一个临时的、一次性子代理,专门处理你的侧面问题
  3. 把答案渲染在一个覆盖层(overlay)  里,而不是内联到主对话
  4. 主任务继续在后台并行运行

用代码的逻辑来理解,大致是这样的:

// 伪代码:Claude Code 中的 /btw 实现逻辑

class ClaudeCodeSession {
  private mainConversationHistory: Message[] = [];  // 主对话历史
  private promptCache: PromptCache;                 // 当前会话的提示缓存
  private uiRenderer: UI;                           // 终端 UI 渲染器
  
  async handleCommand(input: string) {
    // 检测斜杠命令
    if (input.startsWith('/btw ')) {
      const query = input.slice(5);  // 提取问题内容
      
      // 🎯 关键:创建临时子代理,但主会话不中断
      return await this.handleBtwQuery(query);
    }
    
    // 普通消息:加入主对话历史
    this.mainConversationHistory.push({
      role: 'user',
      content: input
    });
    
    return await this.processMainConversation();
  }
  
  private async handleBtwQuery(query: string): Promise<void> {
    // 1️⃣ 从主会话中读取当前上下文(但不修改)
    const currentContext = this.promptCache.getCurrentContext();
    
    // 2️⃣ 创建临时子代理,仅用于回答这个问题
    const tempSubAgent = new TemporarySubAgent({
      context: currentContext,
      toolsEnabled: false,      // ❌ /btw 没有工具访问权限
      maxTokens: 500,           // 轻量级响应,节省 token
      addToHistory: false       // 🔑 不添加到主对话历史!
    });
    
    // 3️⃣ 获取答案
    const answer = await tempSubAgent.query(query);
    
    // 4️⃣ 在覆盖层显示,而不是内联
    this.uiRenderer.showOverlay(answer, {
      onClose: () => {
        // 用户按空格/回车/ESC 后,覆盖层消失
        // 主对话区域完全不受影响
        tempSubAgent.destroy();  // 立即销毁临时代理,释放资源
      }
    });
    
    // 5️⃣ 主对话在后台继续并行运行
    // 没有任何东西被写入 mainConversationHistory
  }
}

📌 核心要点/btw 没有工具访问权限,它不会读文件、不会运行命令、不会改代码。它是一个只读的、快速的知识查询。这种设计让它在性能和成本上都极其轻量。


📊 完整的调用时序图

下面的时序图展示了一次 /btw 调用的完整生命周期:

btw.png


🎯 什么时候用 /btw?

✅ 适合的场景

  1. 快速语法查找:记不清某个函数怎么写了?/btw Python datetime 格式化
  2. 概念澄清/btw 依赖注入是什么
  3. 库的功能确认/btw 这个库的 retry 逻辑是什么
  4. 不打断编码流程的即时提问

❌ 不适合的场景

  • 需要读文件或运行命令
  • 需要多轮对话
  • 需要修改代码
  • 需要深度推理和复杂分析

因为 /btw 没有工具访问权限,它只基于 Claude 的知识和当前会话上下文来回答


💰 省钱的秘密

这个命令还有一个“隐藏福利”——省钱

每次普通对话,你的问题 + Claude 的回答都会被加进对话历史。后续的每一次请求,Claude 都会重新读取整个历史

上下文越堆越长,token 消耗越滚越大。如果用 /btw,侧面问题完全不进入主历史。据用户统计,频繁使用 /btw 的会话中,token 消耗可以减少高达 50%

原理也很简单——/btw 只是一个单轮查询,不会触发完整的代理交互,消耗的 token 只是正常对话的一小部分


🔧 怎么用?

确保你的 Claude Code 版本 ≥ 2.1.72

# 检查版本
claude --version

# 如果版本太旧
claude update

然后正常启动 Claude Code:

claude

在任意时刻——哪怕 Claude 正在干活——直接输入:

/btw 你想问的问题

答案会弹出一个覆盖层。看完按 SpaceEnter 或 Escape 关闭,回到你的主会话。


🏁 最后

/btw 是 Anthropic 团队 Erik Schluntz 作为副项目构建的一个小功能,但它解决的是开发工作流中一个真正让人抓狂的问题

它不是什么火箭科学。它的巧妙之处在于——用最优雅的方式,做了一件最小、但最有价值的事:让 AI 更像人,让对话更自然

就像有个靠谱的同事,一边在帮你改代码,一边能随口回答你的疑问,不会愣在那里问你“我是继续改代码还是先回答你”

这才是 AI 编程助手该有的样子。