We’ve rewritten Claude Code’s terminal rendering system to reduce flickering by roughly 85%.
We wanted to share more about why this was so difficult, how the fix works and how we used Claude Code to fix it 🧵
When rendering in a terminal there are two regions: the viewport at the bottom and the scrollback buffer above it.
When content exceeds the viewport height, the top row gets pushed into scrollback and some of the rendering happens offscreen.
When content exceeds the viewport height, the top row gets pushed into scrollback and some of the rendering happens offscreen.

Unlike regular CLI tools that print output and exit, Claude Code is a long-running interactive UI. We redraw our viewport dozens of times per second.
When we render offscreen or the terminal resizes, we have to clear the scrollback each time. That's the flicker.
When we render offscreen or the terminal resizes, we have to clear the scrollback each time. That's the flicker.

Over the past few months, we've rewritten our rendering system from scratch.
We now diff each cell and emit the minimal escape sequences needed to update what changed. We only do full redraws when we absolutely have to.
We now diff each cell and emit the minimal escape sequences needed to update what changed. We only do full redraws when we absolutely have to.
Why not virtualize scrolling?
When you something like emacs, the terminal switches to an "alternate screen". The program controls everything: scrolling, selection, the works. When you exit, your previous terminal content reappears. This would solve flicker entirely.
When you something like emacs, the terminal switches to an "alternate screen". The program controls everything: scrolling, selection, the works. When you exit, your previous terminal content reappears. This would solve flicker entirely.
However, you no longer get native terminal experiences for things like Cmd+F search, text selection, and copy/paste.
We value this native experience a lot. We may explore alternate screen mode in the future, but our bar is quite high.
We value this native experience a lot. We may explore alternate screen mode in the future, but our bar is quite high.
Why this took so long
We started with almost no tests to verify rendering. It was humbling: fix something, break something else.
What unblocked us was property-based testing. We wrote tests that rendered components through both the old & new systems and diffed them.
We started with almost no tests to verify rendering. It was humbling: fix something, break something else.
What unblocked us was property-based testing. We wrote tests that rendered components through both the old & new systems and diffed them.
The tests generated thousands of random UI states—different widths, content lengths, Unicode edge cases—and verified the new renderer matched the old one.
This created a feedback loop that let Claude Code easily verify its work and make progress on the issue.
This created a feedback loop that let Claude Code easily verify its work and make progress on the issue.
You can read more about this in-depth in Chris's comment on this Github issue: github.com/anthropics/cla…
Generated by Thread Navigator
Press ⌘ + S to quick-export
