Thai: Backspace deletes the whole syllable instead of one combining mark
Summary
In the prompt input box, pressing Backspace on Thai text deletes the entire grapheme cluster (base consonant + vowel + tone mark) in one keypress, instead of removing only the last combining mark. Thai users expect one Backspace = one code point, which is how macOS native text fields and every Thai IME behave.
Repro
- Run
claudein any terminal (reproduced in Harness, Terminal.app, iTerm2) - In the prompt box type
ที่— three code points:U+0E17ท +U+0E35◌ี +U+0E48◌่ - Press Backspace once
Expected: ที (only the tone mark U+0E48 is removed), a second Backspace gives ท, a third clears the box.
Actual: the input box is empty after a single Backspace — all three code points are gone.
Automated repro
Verified with a PTY + terminal-emulator harness (pyte), so this is not a rendering artifact of any one terminal:
[claude] typed: ['❯ ที่']
[claude] BS1 : [] # input box empty after one backspace
Second, related case: U+0E33 (ำ)
Type ซ้ำ — U+0E0B ซ + U+0E49 ◌้ + U+0E33 ำ — and press Backspace once.
Expected: ซ้ (only ำ removed, it is a spacing character occupying its own column).
Actual: the box is empty — all three code points are gone.
ำ decomposes to U+0E4D + U+0E32, so a segmenter that normalizes before splitting folds it
into the preceding cluster. Codex's TUI gets this one right (its Backspace on ซ้ำ leaves ซ้),
so the two CLIs currently disagree on the same input.
Environment
- Claude Code 2.1.226 (native binary install,
~/.local/share/claude/versions/) - macOS 15 (Darwin 25.5.0), Apple Silicon
- Reproduced under
TERM=xterm-256color,LANG=en_US.UTF-8
Notes / reference behavior
- macOS AppKit gets this right:
NSTextView(string: "ที่").deleteBackward(nil)leavesU+0E17 U+0E35, i.e. one code point removed. - zsh's default
backward-delete-charhas the same cluster-deleting behavior whencombiningcharsis set; it is fixable with a widget that trims one Unicode scalar when the trailing scalar is a Thai combining mark (U+0E31,U+0E34–U+0E3A,U+0E47–U+0E4E). A similar rule in the input box would fix this. - The same issue affects other scripts that stack multiple combining marks (Lao, Khmer, Devanagari), where per-cluster deletion is also not the platform convention.
- Deleting the whole cluster is correct for emoji ZWJ sequences and precomposed Latin (
é) — the fix should be scoped to combining-mark scripts, not applied to all clusters.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗