Terminal renderer miscalculates line width with ANSI escape codes, causing text corruption on Windows
Bug Report: Terminal renderer miscalculates line width with ANSI escape codes, causing text corruption
Description
Inline code blocks (backticks) and other styled text render incorrectly in the terminal. Text appears shifted, truncated, or wrapped at wrong positions. This appears to be caused by ANSI escape codes being counted as visible characters during line width calculation.
Environment
- Claude Code Version: 2.0.73
- OS: Windows 10/11
- Terminal: Windows Terminal (WT_SESSION present)
- Shell: Git Bash (bash.exe)
- TERM: xterm-256color
Steps to Reproduce
- Run Claude Code in Windows Terminal with Git Bash
- Ask Claude a question that results in a response containing inline code (backticks) with a long path or text
- Example prompt: "Do you see the Schedule.xlsx file in the admin folder?"
- Claude responds with text like:
``D:\Projects\Schedule\Admin\Schedule.xlsx
Yes, I can see **Schedule.xlsx** in the Admin folder at:
``
Expected Behavior
The path should render correctly on one or two lines with proper wrapping.
Actual Behavior
The text is corrupted:
- Line 1 shows: "Yes, I can see Schedule.xlsx in the Admin folder at:"
- Line 2 shows (with large left indent): "edulars\Admin\Schedule.xlsx"
The beginning of the path ("D:\Projects\Schedule") is missing or pushed off-screen. The continuation line has incorrect indentation.
Bullet lists following styled text also render incorrectly with items appearing fragmented or in wrong positions.
Root Cause Analysis
The terminal renderer appears to count ANSI escape codes (used for inline code styling) as visible characters when calculating line width for wrapping. For example:
- Escape codes like
\x1b[48;5;240m(background color) add ~12 invisible bytes - These are counted in the string length calculation
- This shifts the calculated cursor position
- When text wraps, the continuation appears at incorrect column positions
Evidence
- Issue only affects styled content (inline code, bold, etc.)
- Plain text without markdown formatting renders correctly
- The offset appears proportional to the number of styling codes applied
Workaround
Setting NO_COLOR=1 environment variable before launching Claude Code may disable ANSI styling and avoid the issue (not fully tested).
Additional Context
This issue has been reported by multiple users on Twitter, suggesting it's a widespread problem affecting Windows Terminal users.
19 Comments
Have same issue since today. use windows as well, and Jet Brain Rider ide together with Claude code.
same issue here
Same. Just started happening when I started a new session. Using CC in VS code and tested in Windows CMD just to rule out VS Code. Same results. Missing/partial sentences, lots of extra random whitespaces/lines and line breaks mid-word.
I have the same problem with the Claude Code client for Windows!
It's really hard to understand what's written!
Same started happening to me today. I find it's more often happening in Powershell than CMD
same, in windows git bash and macos bash same.
same issue. on v2.0.76
+1
This issue persists in the latest version.
Environment:
Observations:
"disableAllHooks": truein settingsScreenshot:
<img width="1662" height="141" alt="Image" src="https://github.com/user-attachments/assets/54d59a8a-408a-4639-8772-8c2322e17116" />
<img width="718" height="179" alt="Image" src="https://github.com/user-attachments/assets/2b58a7f0-5eaf-457e-bb38-008dbfe00fb8" />
<img width="899" height="464" alt="Image" src="https://github.com/user-attachments/assets/31d89a14-b463-4480-9a2b-63880b9d45d0" />
This was bothering me too for a while. Here's a dirty patch for postinstall:
Update: can I just update the patch because like why not and it can be useful for someone?
Color Shift Bug Fix
Root Cause
In
cli.jsline 599, theyv3function applies styles to wrapped text using a style map created byxv3. The bug occurs because:f_/Flfunction) normalizes text:.normalize().replaceAll("\r\n", "\n")xv3) was created from unnormalized style object textsyv3uses the normalized text lengthWhy all 4 conditions are required
F.length > 1)yv3multi-line code path is only executed when text wrapsThe Fix
Normalize style object texts before creating the style map:
What the fix does
Nto normalize text:A=>A.normalize().replaceAll("\r\n","\n")xv3:F.map(_=>({..._,text:N(_.text)}))yv3:N(H)<img width="377" height="355" alt="Image" src="https://github.com/user-attachments/assets/52d8c6ba-afca-4942-af8b-6ffd54e087cb" />
and what‘s this?
version:claude code 2.1.5
os:macOS
Unfortunately, this won't work with "native" installation -- as it's a single massive .exe digitally signed.
And as of v2.1.19 they seem to handle this differently, so they've made changes there but did not fix the issue.
But I liked @babanga 's way of thinking. So, for anyone terminally desperate, here's a gist. It's an old-school runtime patcher to fix the vibe-coded slop: no you don't need to remove
\rfrom every\r\njust because it is Windows! At least I restored my sanity, at least in Windows 10 - Windows Terminal - PowerShell - GitBash -- markdown formatting is properly aligned once again. But you need to be really desperate to use it, as runtime patcher is an overkill.Root Cause Found & One-Line Fix
The bug is in the
IP5function incli.js(the Ink TUI text renderer). This function applies ANSI styles to word-wrapped text by walking through both the wrapped output and the original text in parallel, using a position tracker$and a style mapK[$].The problem: When word-wrapping breaks a line at a space, that space is consumed (removed from the wrapped output). But
$only advances once per character of the wrapped text. After each line break,$is behind by 1 (the consumed space). This accumulates: after N line wraps, styles are shifted N characters to the right.The fix already exists in the code — it's just gated behind trim mode. The
IP5function has a whitespace-position-correction block that detects when the original text has whitespace at$but the wrapped line doesn't start with whitespace, and skips past the consumed space. But this logic is behindif(z&&_.length>0)wherezis only true in"wrap-trim"mode. The default"wrap"mode never runs it.The Fix
In the
IP5function, change:to:
That's it. Remove
z&&from the condition. The whitespace correction now runs in all wrapping modes, not just trim.Why This Explains All Observed Behavior
M.length===1), so they go through a different branch that appliesTy1to whole lines — no position tracking needed.M.length > 1), hitting theIP5path where the bug lives.How to Apply
Search
cli.jsforz&&_.length>0— there's exactly one match. Remove thez&&. Tested on 2.1.33, completely eliminates the prose highlighting drift.Note: if you ask Claude Code to fix itself using this information, it can locate and patch the function automatically.
Update: Second patch needed for plan mode / indented content
The original fix (removing
z&&from the start-of-line whitespace correction) resolves drift for regular prose, but plan mode content with indented markdown (bullet lists, numbered steps, sub-items) still drifts.Why
The start-of-line whitespace skip has a condition
!Wthat checks whether the current wrapped line starts with non-whitespace. For indented continuation lines (common in plan mode markdown), the line DOES start with whitespace, soWis true and!Wis false — the correction is skipped entirely.There's a second whitespace correction block at the end of the line loop in
IP5that uses look-ahead matching instead. It finds the first character of the next wrapped line and advances$until it aligns. This handles indented content correctly. But it was also gated behindz&&(trim-mode only).Complete fix (two changes in
IP5)Change 1 (start-of-line, handles non-indented wraps):
Change 2 (end-of-line, handles indented/plan content wraps):
Both changes are the same: remove
z&&so the whitespace correction runs in all wrap modes, not just"wrap-trim".How to apply
Search
cli.jsforz&&— within theIP5function there are exactly two occurrences. Remove both. Confirmed working on 2.1.33 for both regular prose and plan mode with indented markdown content.This PowerShell script patches the Claude exe on Windows binary installation. Thanks to all of you who investigated and found the cause. Needs to be executed after auto-update too.
@claude Could somebody please pay attention to this issue? It is a know reproducable bug for months with considerable impact on the usabiltiy of your product, for everyone using it on windows. it also has probable root-cause and a fix associated with it.
This hook worked for me. I am using CC native ARM64 binary. I know the pattern is the same in the other architectures' binaries, but I don't know if there are any differences to take into account. You could start with these and ask Claude to check them and implement them according to your current installation.
OneDrive Folder with Hook
If anyone can get the attention of anthropic devs to implement a fix of the root cause (as identified by @WargameGPT above) that would be super.
@ant-kurt, @bcherny, @ashwin-ant, @fvolcic
Closing for now — inactive for too long. Please open a new issue if this is still relevant.
This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.