Feisky 让 AI 成为你的第二大脑

AI

Claude Code 终于不闪了:全屏渲染模式详解

Claude Code 推出全屏渲染模式(NO_FLICKER),彻底解决终端闪烁、内存膨胀和滚动跳跃问题。本文详解开启方式、技术原理和使用技巧,特别适合 VSCode 终端、WSL、SSH 等慢速环境用户。

用 Claude Code 跑过长会话的人,应该都经历过这种场景:在 Claude Code 长会话中输入新消息后,终端在那疯狂刷屏,屏幕不停闪烁,你想看一眼前面的上下文,得等所有历史会话消息全部都刷一遍屏。

我自己平时在 tmux 里跑 Claude Code,会话长了之后这个闪烁就很明显,但还能忍。真正让我受不了的是在 VSCode 集成终端或者 SSH 连接到服务器的时候,终端渲染本来就慢,再加上 Claude Code 每次输出都要刷新整个屏幕,长会话到后面很长时间都在等刷屏了。网络延迟再叠上渲染延迟,这体验简直了。

这个痛点社区里吐槽很久了,现在终于等来了修复。愚人节当天, Claude Code 负责人 Boris Cherny 宣布了全屏渲染模式,通过环境变量 CLAUDE_CODE_NO_FLICKER=1 开启。

一行配置,立竿见影

开启方式很简单,启动时加个环境变量:

CLAUDE_CODE_NO_FLICKER=1 claude

不想每次都敲这一串的话,扔到 shell 配置文件里:

# 加到 ~/.zshrc 或 ~/.bashrc
export CLAUDE_CODE_NO_FLICKER=1

也可以写进 Claude Code 的 settings.json

{
  "env": {
    "CLAUDE_CODE_NO_FLICKER": "1"
  }
}

我加上之后第一感觉就是终于安静了。输入框固定在屏幕底部,Claude Code 的输出在上方平滑滚动,不再有那种整屏闪一下的刷新。整个体验和 vim、htop 这类全屏终端程序一样,Claude Code 接管了整个终端画面。

全屏模式的整体布局:工具调用结果展开显示,输入框固定在底部,状态栏实时显示执行进度

为什么终端会闪

不闪了当然好,但我比较好奇的是:为什么以前一定会闪?这到底是 Claude Code 的 bug,还是终端本身的限制?翻了 Boris 的推文线程,发现答案是后者。

终端不是浏览器。浏览器有 DOM、有 CSS、有 GPU 加速的合成器,想更新页面某个区域,直接改那个区域就行。终端能用的只有 ANSI 转义码,一套上世纪 70 年代设计的指令集:移动光标到 (x, y)、在当前位置写一段文字、清除一行、清除整个屏幕。

关键问题在于,ANSI 转义码没有移动光标到屏幕外某一行的指令。也就是说,当 Claude Code 的输出已经超出屏幕之后,你没办法只更新那一行。想要重新渲染,唯一的办法就是清空整个屏幕然后重画。

这就是闪烁的根源。每次 Claude Code 输出新内容,传统渲染器都要:清屏 → 重绘所有可见内容 → 把光标移到正确位置。会话越长,需要重绘的内容越多,闪烁越严重,CPU 和内存占用也跟着线性增长。

全屏模式怎么解决的

那 Claude Code 团队是怎么绕过这个限制的呢?

思路其实不复杂,也就是换成了虚拟滚动。就像在前端设计中,一个长列表有一万条数据,你不会把一万个 DOM 节点全渲染出来,只需要渲染可见的那几十条。Claude Code 的全屏模式做的是同样的事,只不过对象从 DOM 节点变成了终端字符行。

具体来说,传统模式下 Claude Code 把所有内容都写到终端的主滚动缓冲区里,让终端自己处理滚动。新模式切换到终端的备用屏幕缓冲区,然后自己接管所有的滚动、鼠标和键盘事件。

这样做的好处是,渲染器只需要画当前终端可见的内容。一个 2 小时的长会话,可能积累了几百条消息,但屏幕上一次最多显示几十行。只渲染这几十行,CPU 和内存占用就变成了常量,不会随着会话长度增长。

向上滚动查看历史会话,视口只渲染当前可见内容

这对慢速终端环境来说改善特别明显。VSCode 的集成终端、tmux、iTerm2 这些渲染吞吐量本来就是瓶颈的场景,以前长会话到后面明显卡顿。现在每帧需要发送给终端的数据大幅减少,这些环境下的体验提升是最大的。

不只是不闪了

全屏模式顺带解锁了一些之前终端里做不到的交互。

鼠标支持是让我比较意外的。开启后可以直接用鼠标点击输入框来移动光标,以前想在输入框里改个词,得按方向键一个字一个字挪过去,现在直接点一下就到位了。折叠的工具调用结果也可以点击展开,URL 和文件路径点了直接打开。

选择文字的体验也有改善。以前在终端里选 ClaudeCode 的输出,会连带选上行号和 UI 边框,粘贴出来会带上这些多余的字符。现在选择是在应用层处理的,只选到实际内容,松开鼠标直接复制到剪贴板。双击选词时文件路径会被当作一个完整单元选中。

滚动方面,用鼠标滚轮或者键盘快捷键都行:

快捷键功能
PgUp / PgDn上下翻半屏
Ctrl+Home跳到会话开头
Ctrl+End跳到最新消息,恢复自动跟随
鼠标滚轮逐行滚动

MacBook 没有 PgUp/PgDn 键的话,用 Fn+↑Fn+↓ 代替。

往上滚动查看历史时,自动跟随会暂停,新输出不会把你拽回底部。想回去接着看最新进展,按 Ctrl+End 或者滚到底部就行。以前最烦的就是想回头看看上面的代码,Claude Code 一输出新内容就把你弹回底部了,现在不会了。

搜索怎么办

全屏模式有一个变化需要适应:因为内容在备用屏幕缓冲区里,终端自带的 Cmd+F 搜索和 tmux 的搜索功能都用不了了。不过全屏模式提供了替代方案。

Ctrl+O 进入转录模式,支持一套 vim 风格的导航:

按键功能
/打开搜索,输入关键词后回车确认
n / N跳到下一个/上一个匹配
j / k逐行滚动
g / G跳到顶部/底部
qEsc退出转录模式

如果你就是想用终端原生的搜索功能,也有办法。在转录模式下按 [,会把整个会话内容写回终端的主滚动缓冲区,这时候 Cmd+F 和 tmux 的复制模式就都能用了。

几个需要注意的地方

这个模式目前还是 Research Preview 状态,我用下来碰到几个需要适应的地方。

复制粘贴的行为变了。选中文字后松开鼠标就自动复制到剪贴板,不需要再 Cmd+C。如果你更喜欢手动控制,可以在 /config 里关掉 Copy on select,改用 Ctrl+Shift+C

鼠标滚轮的速度在不同终端上差异挺大。VSCode 终端里滚轮每次只走一行,太慢了。调一下这个环境变量:

export CLAUDE_CODE_SCROLL_SPEED=3

值域 1 到 20,3 大概相当于 vim 的默认滚动速度。

在 tmux 里使用需要开启鼠标模式。如果你的 ~/.tmux.conf 里还没有这行,加一下:

set -g mouse on

不过要注意,iTerm2 的 tmux 集成模式(tmux -CC)和全屏渲染不兼容(普通的 tmux 没问题)。

如果你通过 SSH 使用,或者在 tmux 里选文字时遇到剪贴板的问题,可以关掉鼠标捕获,只保留无闪烁渲染:

CLAUDE_CODE_NO_FLICKER=1 CLAUDE_CODE_DISABLE_MOUSE=1 claude

这样键盘滚动、固定输入框、常量内存这些核心好处都还在,只是鼠标相关的功能回到了终端原生行为。

写在最后

解决终端渲染性能问题有不同的思路。Warp 当年选择从底层重写终端模拟器,用 GPU 渲染。Claude Code 走的是另一条路:不改终端,在应用层做虚拟滚动,只渲染可见区域。Claude Code 的做法有个明显优势,它适用于任何终端,不管你是在 iTerm2、Ghostty 还是 WSL 默认的那个终端里,加个环境变量就都能用。

这个模式目前还是 Research Preview,滚动物理效果和选文字的边界判断偶尔还有点问题。但和以前的闪烁比起来这些都是小问题。如果你也在 VSCode 终端或者 SSH 环境里被刷屏折磨过,加个 CLAUDE_CODE_NO_FLICKER=1 试试。


相关资源:


欢迎长按下面的二维码关注 Feisky 公众号,了解更多云原生和 AI 知识。

Feisky 公众号二维码

相关文章

目录

本页目录