You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Bug]: macOS terminal clips CJK glyphs at the cursor — cursor lands on the wide character's first cell; cursor style/opacity ignored #12729
When the cursor sits at the end of a run of CJK (full-width) text in an Orca terminal, the cursor is painted as a single-cell block over the first cell of the last wide character, and the right half of that glyph is never drawn. The character becomes unreadable.
Typing 가나다라 renders as:
› 가나다█ ← 'ㄹ' visible inside a 1-cell black block, 'ㅏ' missing entirely
This is not an IME problem (distinct from #9803, which is Windows/IME): it persists after the composition is committed, and it reproduces at a plain zsh prompt with no TUI running.
Two defects appear to be involved:
Cursor lands on the wrong cell — on the wide character's starting cell instead of the column the application requested.
terminalCursorStyle / terminalCursorOpacity have no effect — with "bar" and 0.1 stored in settings, the cursor still renders as a fully opaque block.
Reproduce
macOS, open a new terminal tab in Orca.
At a plain zsh prompt, type 가나다라.
The final character shows only its left half inside a black block.
Reproduces in a freshly created tab, so it is not stale-instance state.
The application requests the correct column
Captured from a pty running the same TUI, immediately after sending 가나다라 (no Enter). Raw output, escapes made visible:
Pixel measurements from a 4320×2344 screenshot (D2CodingLigature Nerd Font Mono, size 14):
Quantity
Value
Cell width (from the cursor block)
14 px
Korean glyph advance (가→나→다→라)
28 px
Ratio
exactly 2 cells — font metrics are correct
Cursor block width
14 px (1 cell) — covers only the glyph's left half
Deriving columns (prompt › at col 1, x = 23; cell width 14 px):
Expected
Observed
Cursor x
164
134
Cursor column
11
9 (= first cell of 라)
The cursor is placed two cells left of the requested column — on the wide character's starting cell — and painting that cell clips away the glyph's right half.
Settings that do NOT affect it
Each verified individually; the defect is identical in every combination:
terminalLineHeight: 1 → 1.3
terminalCursorStyle: block → bar
terminalCursorOpacity: default → 0.1
terminalGpuAcceleration: auto → off (DOM renderer)
terminalFontFamily: …Nerd Font Mono → …Nerd Font
Fresh terminal tab vs. existing tab
Note that "bar" and 0.1 are persisted in orca-data.json yet the rendered cursor stays an opaque block, so those options seem not to reach the xterm instance.
Related code in the shipped bundle
The bundle already models this class of problem, but the mitigation is gated to Windows and so never runs on macOS:
isEastAsianRendererRiskCodePoint() covers Hangul syllables (U+AC00–U+D7FF) and is combined with sgrSequenceSetsBackground() (SGR 40–47 / 100–107 / 48).
Its caller is guarded by state.isWindowsClient / state.isNativeWindowsConpty.
getTerminalWebglAutoDecision() inspects Linux hosts only; on macOS it returns { allowWebgl: true, reason: "non-linux" }, so terminalGpuAcceleration: "auto" always keeps WebGL enabled.
Expected behaviour
With the cursor on or after a full-width character, the whole glyph stays legible — either the cursor spans both cells of the wide character, or it is drawn on the column the application actually requested. Additionally, terminalCursorStyle and terminalCursorOpacity should take effect.
Typing Korean at a Claude Code prompt, the syllable under the cursor renders with only its left half visible — the right half of the glyph is never drawn. Moving the cursor away restores the character, so the damage is confined to the cell the cursor occupies.
Two details that match your cursor-cell analysis:
Latin text is unaffected. Single-cell glyphs are fully covered by the one-cell cursor block, so nothing appears to be missing. The defect only becomes visible with two-cell (full-width) characters.
It is not composition state. The clipped glyph is already committed text — it just happens to be the character the cursor is sitting on. Pressing Enter makes it look correct simply because the cursor moves elsewhere.
Ruled out on my machine
I chased this as a font problem before finding this issue, and can confirm the font axis is a dead end. Switching the interface font between Geist, Pretendard Variable, and D2CodingLigature Nerd Font Mono changes nothing. I also measured the vertical metrics of every candidate at 14px against the 20px line box — D2Coding 16.24px, Pretendard 16.71px, Apple SD Gothic Neo 16.80px — all fit with room to spare, so there is no metric overflow involved.
Happy to run an instrumented build or capture additional traces if that would help.
Resolved — and your measurements were right, which is what took the longest to reconcile.
The black block is not the cursor. It is the box drawn over the terminal while an input method is still assembling a character. macOS 2-Set Korean keeps the final syllable composing until a terminator, so after 가나다라 only 가나다 has reached the shell and 라 sits in that overlay. In your version the overlay used stock colours — black on white — which is the block you saw.
A block cursor could not have produced it: it inverts a cell, it cannot mask half a glyph, and on the renderer Orca uses by default it spans both cells of a wide character. That rules out the cursor explanation on both renderers, not just one.
It also explains everything else in your report: the block sits at the composing cursor cell, no cursor setting reaches it, it looks identical with GPU acceleration off because it is drawn above both renderers, Latin never triggers it because Latin opens no composition, and pressing Enter clears it because Enter commits the composition.
Already fixed.#15014 themes that overlay from your terminal theme and renders the row it covers. It landed on 2026-08-17; v1.4.184 was tagged 2026-08-16, so it missed your build by one day and ships in the next release.
On your one-cell measurement, which I owe you a correction for. I initially argued it was self-referential. It was not — your report contained an independent measurement that backed it up, and I was wrong to wave it away.
The reason it conflicted: the overlay has no width of its own, so it is exactly as wide as the glyph renders. With a font that has no Korean glyphs it collapses to about one cell. We added a browser-level test that measures it, and confirmed both halves:
without a Korean font installed: 1.02 cells
with a Korean font installed: wider than 1.5 cells (passes)
So your measurement was accurate for your setup, and the overlay is genuinely two cells wide when the font can draw the character. Both true at once.
Two things came out of this that outlive the issue: a test that pins the block as the overlay so the cursor explanation cannot be re-derived, and a CJK font on our test machines — without which none of our tests could tell a real result from a missing glyph.
Thank you for the pixel measurements. They were the part that did not fit, and chasing why is what produced the actual answer.
Activity
bongho commentedon Aug 18, 2026
Still reproduces on 1.4.184 (this issue was filed against 1.4.170).
Environment
terminalFontFamily:D2CodingLigature Nerd Font Mono,terminalFontSize: 13,terminalFontWeight: 500,terminalLineHeight: 1terminalCursorStyle:blockWhat I see
Typing Korean at a Claude Code prompt, the syllable under the cursor renders with only its left half visible — the right half of the glyph is never drawn. Moving the cursor away restores the character, so the damage is confined to the cell the cursor occupies.
Two details that match your cursor-cell analysis:
Ruled out on my machine
I chased this as a font problem before finding this issue, and can confirm the font axis is a dead end. Switching the interface font between
Geist,Pretendard Variable, andD2CodingLigature Nerd Font Monochanges nothing. I also measured the vertical metrics of every candidate at 14px against the 20px line box — D2Coding 16.24px, Pretendard 16.71px, Apple SD Gothic Neo 16.80px — all fit with room to spare, so there is no metric overflow involved.Happy to run an instrumented build or capture additional traces if that would help.
test(terminal): pin that the CJK block is the preedit overlay, not th…
test(terminal): make the cursor precedence assertion real and measure…
test(terminal): pin that the CJK block is the preedit overlay, not th…
test(terminal): make the cursor precedence assertion real and measure…
ci(e2e): install a CJK font on the e2e runners
ci(e2e): install a CJK font on the e2e runners (#15259)
test(terminal): pin that the CJK block is the preedit overlay, not th…
test(terminal): make the cursor precedence assertion real and measure…
test(terminal): pin that the CJK block is the preedit overlay, not th…
nwparker commentedon Aug 18, 2026
Resolved — and your measurements were right, which is what took the longest to reconcile.
The black block is not the cursor. It is the box drawn over the terminal while an input method is still assembling a character. macOS 2-Set Korean keeps the final syllable composing until a terminator, so after
가나다라only가나다has reached the shell and라sits in that overlay. In your version the overlay used stock colours — black on white — which is the block you saw.A block cursor could not have produced it: it inverts a cell, it cannot mask half a glyph, and on the renderer Orca uses by default it spans both cells of a wide character. That rules out the cursor explanation on both renderers, not just one.
It also explains everything else in your report: the block sits at the composing cursor cell, no cursor setting reaches it, it looks identical with GPU acceleration off because it is drawn above both renderers, Latin never triggers it because Latin opens no composition, and pressing Enter clears it because Enter commits the composition.
Already fixed. #15014 themes that overlay from your terminal theme and renders the row it covers. It landed on 2026-08-17; v1.4.184 was tagged 2026-08-16, so it missed your build by one day and ships in the next release.
On your one-cell measurement, which I owe you a correction for. I initially argued it was self-referential. It was not — your report contained an independent measurement that backed it up, and I was wrong to wave it away.
The reason it conflicted: the overlay has no width of its own, so it is exactly as wide as the glyph renders. With a font that has no Korean glyphs it collapses to about one cell. We added a browser-level test that measures it, and confirmed both halves:
So your measurement was accurate for your setup, and the overlay is genuinely two cells wide when the font can draw the character. Both true at once.
Two things came out of this that outlive the issue: a test that pins the block as the overlay so the cursor explanation cannot be re-derived, and a CJK font on our test machines — without which none of our tests could tell a real result from a missing glyph.
Thank you for the pixel measurements. They were the part that did not fit, and chasing why is what produced the actual answer.
ci(e2e): install a CJK font on the e2e runners (stablyai#15259)
test(terminal): pin that the CJK block is the preedit overlay, not th…
ci(e2e): install a CJK font on the e2e runners (stablyai#15259)
test(terminal): pin that the CJK block is the preedit overlay, not th…
ci(e2e): install a CJK font on the e2e runners (stablyai#15259)
test(terminal): pin that the CJK block is the preedit overlay, not th…