🍕 那个憋屈的瞬间
想象一个场景——
你走进餐厅,刚坐下就点了一份豪华披萨。服务员小哥转身走了,披萨开始在后厨烤。
突然你渴了,想加一杯可乐。你朝服务员招手——
他看了你一眼,说:“先生不好意思,我正在为您烤披萨。等我烤完再来招呼您。”
你:???
这不就是以前用 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 不会把这个请求添加到主对话历史中。它会:
用代码的逻辑来理解,大致是这样的:
// 伪代码: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?
✅ 适合的场景:
- 快速语法查找:记不清某个函数怎么写了?
/btw Python datetime 格式化 - 概念澄清:
/btw 依赖注入是什么 - 库的功能确认:
/btw 这个库的 retry 逻辑是什么 - 不打断编码流程的即时提问
❌ 不适合的场景:
- 需要读文件或运行命令
- 需要多轮对话
- 需要修改代码
- 需要深度推理和复杂分析
因为 /btw 没有工具访问权限,它只基于 Claude 的知识和当前会话上下文来回答。
💰 省钱的秘密
这个命令还有一个“隐藏福利”——省钱。
每次普通对话,你的问题 + Claude 的回答都会被加进对话历史。后续的每一次请求,Claude 都会重新读取整个历史。
上下文越堆越长,token 消耗越滚越大。如果用 /btw,侧面问题完全不进入主历史。据用户统计,频繁使用 /btw 的会话中,token 消耗可以减少高达 50% 。
原理也很简单——/btw 只是一个单轮查询,不会触发完整的代理交互,消耗的 token 只是正常对话的一小部分。
🔧 怎么用?
# 检查版本
claude --version
# 如果版本太旧
claude update
然后正常启动 Claude Code:
claude
在任意时刻——哪怕 Claude 正在干活——直接输入:
/btw 你想问的问题
答案会弹出一个覆盖层。看完按 Space、Enter 或 Escape 关闭,回到你的主会话。
🏁 最后
/btw 是 Anthropic 团队 Erik Schluntz 作为副项目构建的一个小功能,但它解决的是开发工作流中一个真正让人抓狂的问题。
它不是什么火箭科学。它的巧妙之处在于——用最优雅的方式,做了一件最小、但最有价值的事:让 AI 更像人,让对话更自然。
就像有个靠谱的同事,一边在帮你改代码,一边能随口回答你的疑问,不会愣在那里问你“我是继续改代码还是先回答你”。
这才是 AI 编程助手该有的样子。