[BUG] AltGr characters are lost in Windows Terminal since the kitty keyboard protocol is enabled unconditionally

Status Open
Reported on v2.1.273
Maintainer reply None cached
Activity 3 comments · opened Sep 16, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

AltGr characters are lost in Windows Terminal since the kitty keyboard protocol is enabled unconditionally

Environment

| | |
|---|---|
| Claude Code | 2.1.273 (broken); 2.1.270 and 2.1.272 contain the same code; 2.1.124 works |
| Install | native Windows binary, %USERPROFILE%\.local\bin\claude.exe |
| Terminal | Windows Terminal 1.25.1912.0 |
| OS | Windows 11 Pro 26200 |
| Keyboard | French AZERTY (any layout that uses AltGr is affected) |

Summary

On Windows, AltGr is physically reported as Ctrl+Alt. When Claude Code enables the kitty
keyboard protocol, Windows Terminal reports AltGr key presses as CSI u sequences carrying
the alt modifier and the base key, instead of delivering the character produced by
the keyboard layout. Claude Code's AltGr fallback never fires, and the character is lost.

On a French AZERTY layout this silently kills every character on the third level:
€ # { [ | \ ] }. Only the combinations whose base key is non-ASCII (à, é, è, ç)
still work, because the terminal does not disambiguate those.

The same claude.exe run from a WSL shell in the same Windows Terminal window is not
affected: there the byte stream comes from the Linux pty, which never requested the
protocol.

Measurement

A small Win32 program puts CONIN$ in ENABLE_VIRTUAL_TERMINAL_INPUT, forces the console
code pages to 65001, emits a given mode sequence, and dumps the raw bytes received.
Key presses: AltGr+E (€), AltGr+8 (\), AltGr+0 (@), AltGr+6 (|), plain E.

| Mode requested | AltGr+E | AltGr+8 | AltGr+0 | AltGr+6 | E |
|---|---|---|---|---|---|
| none | E2 82 AC ✅ | \ ✅ | @ ✅ | | ✅ | E |
| ESC[>4;2m | E2 82 AC ✅ | \ ✅ | @ ✅ | | ✅ | E |
| ESC[<u ESC[>5u | ESC[101;3u ❌ | ESC[95::56;3u ❌ | @ ✅ | ESC[45::54;3u ❌ | E |
| ESC[>1u | ESC[101;3u ❌ | ESC[95;3u ❌ | @ ✅ | ESC[45;3u ❌ | E |
| ESC[>0u | E2 82 AC ✅ | \ ✅ | @ ✅ | | ✅ | E |

Conclusions:

  • modifyOtherKeys (ESC[>4;2m) is harmless.
  • The disambiguation flag alone (>1u) already breaks AltGr; flag 4 only adds the

alternate-key sub-parameters. So this is not about "report alternate keys".

  • With flags 0, everything works — which is the behaviour Claude Code had before.
  • Note the modifier: ;3u decodes to 3 - 1 = 2, i.e. alt only. Windows Terminal

strips the Ctrl half of AltGr, so the combination never looks like Ctrl+Alt to the
application.

Root cause

Three things combine.

1. The capability is forced on for Windows Terminal, with no way out.
The terminal table used to settle extendedKeys contains "windows-terminal", and the
resolver returns {settled: true} for any terminal in that table — no probe, no
environment override. process.env.WT_SESSION is what makes the terminal resolve to
"windows-terminal".

2. Clearing WT_SESSION does not help, because the capability probe then runs and
Windows Terminal answers ESC[?0u to ESC[?u, which settles extendedKeys to true
anyway (answer("extendedKeys", true, "probe: …")).

3. The AltGr fallback cannot fire. The guard starts with

if (!(key.ctrl && key.meta) || key.super) return false;

and only consults CLAUDE_CODE_ALTGR_AS_TEXT after that test. Since Windows Terminal
reports AltGr with the alt modifier only, key.ctrl is false and the function returns
immediately. The escape hatch documented for exactly this situation therefore has no
effect — confirmed empirically: setting CLAUDE_CODE_ALTGR_AS_TEXT=1 changes nothing.

Even if the guard were reached, the branch builds the character with
String.fromCodePoint(code) where code is the key code (101 = e), not the produced
character (8364 = €). Recovering the real character would require kitty flag 16 (*report
associated text*), which is not requested — the pushed flag set is 5 (1 + 4).

Regression

Version 2.1.124 emits the same kind of sequence but never reaches that code path under
Windows Terminal: it contains an explicit guard,

if (process.env.WT_SESSION) return false;

That guard is gone in 2.1.273, while the terminal table is unchanged — it still lists
"windows-terminal" in both versions. So the regression is the removal of the Windows
Terminal exclusion, not a change in the terminal list or in terminal detection.

Suggested fixes (any one of them)

  1. Restore the Windows Terminal exclusion for the extended-keys capability, or push

flags 0 there. Least risk, restores 2.1.124 behaviour exactly.

  1. Relax the AltGr guard to also accept a key carrying the alt modifier alone on

Windows, so CLAUDE_CODE_ALTGR_AS_TEXT becomes usable — and honour the variable
before the modifier test, so users have a working escape hatch.

  1. Request flag 16 (report associated text) alongside the current flags, and parse

the third CSI u parameter. Note the current regex stops at the modifier group, so
ESC[101;3;8364u would not match today:

``
/^\x1b\[(\d+)(?::(\d*)(?::(\d+))?)?(?:;(\d+))?u/
``

  1. At minimum, **provide an environment variable that disables the extended-keys

capability**. Today there is none: CLAUDE_CODE_SESSION_KIND=bg is the only value that
settles it to false, and it changes far too much else to be usable interactively.

Fix 1 or 2 would benefit every AltGr layout — French, German, Spanish, Polish, Nordic —
not just this one.

Reproduction

  1. Windows Terminal, native Windows Claude Code 2.1.273, any layout with an AltGr level.
  2. Start claude and press AltGr+E on a French AZERTY keyboard.
  3. Expected: € is inserted. Actual: nothing is inserted.
  4. CLAUDE_CODE_ALTGR_AS_TEXT=1 makes no difference.
  5. The same binary launched from a WSL shell in the same window behaves correctly.

What Should Happen?

Pressing AltGr+E on a French AZERTY keyboard should insert "€" into the prompt.
More generally, every AltGr combination should insert the character produced by the
keyboard layout: € # { [ | \ ] } on AZERTY, and the equivalent third-level characters
on any other layout that uses AltGr (German, Spanish, Polish, Nordic).

This is what Claude Code 2.1.124 does in the same Windows Terminal window, and what
2.1.273 itself still does when launched from a WSL shell in that same window.

Additionally, CLAUDE_CODE_ALTGR_AS_TEXT=1 should have an observable effect. It is the
documented escape hatch for this exact situation, but it currently changes nothing
because it is only consulted after a key.ctrl && key.meta test that AltGr never
satisfies on Windows Terminal.

Error Messages/Logs

None.

Steps to Reproduce

Launch claude.exe, then press AltGr+E on a French AZERTY keyboard.

Claude Model

Opus

Is this a regression?

Yes, this worked in a previous version

Last Working Version

2.1.124

Claude Code Version

2.1.273

Platform

Other

Operating System

Windows

Terminal/Shell

Windows Terminal

Additional Information

_No response_

View original on GitHub ↗

3 Comments

romain-rossi · 26 days ago

Still reproduces on 2.1.276 (native Windows build). Same setup as the report, on a newer OS build: Windows Terminal Preview 1.25.1912.0, Windows 11 Pro Insider Preview 25H2 (build 26220.9472), French AZERTY, PowerShell 7.

The guard is unchanged in the 2.1.276 bundle: if(!(n.ctrl&&n.meta)||n.super)return!1 still runs before CLAUDE_CODE_ALTGR_AS_TEXT is read. Extended keys are settled to true as soon as the terminal resolves to windows-terminal, and I found no environment variable to turn that off.

Workaround that works here: run Claude Code in the classic console host instead of Windows Terminal (Win+R, conhost.exe pwsh, then claude). AltGr is back. Some glyphs render poorly, nothing else so far.

Unsetting WT_SESSION before launching does not help. Without it the AltGr mode resolves to "off".

On scope: the Windows Terminal release notes introduce the kitty keyboard protocol in 1.25 Preview (v1.25.622.0), and the current stable 1.24.11911.0 does not mention it. Only Preview users are hit today. Every AltGr layout on Windows will be once 1.25 reaches stable.

If you land here from IntelliJ with the same symptom: for me that was the JetBrains "Reworked" terminal (IJPL-254887), fixed by switching back to the classic terminal. Unrelated to this bug.

pelifix · 20 days ago

Same problem here, on Norwegian keyboard layout.

  • Claude Code: 2.1.281 (native Windows, claude.exe)
  • Terminal: Windows Terminal Preview 1.25.1912.0
  • OS: Windows 11 Enterprise 10.0.26200
  • Layout: Norwegian (nb-NO): { = AltGr+7, [ = AltGr+8, ] = AltGr+9, } = AltGr+0

None of {[]} can be typed into the Claude Code prompt. The same keys work in PowerShell and in WSL bash in the same Windows Terminal Preview window.
Pasting works.

joelhecht · 9 days ago

For some unknown reason, this problem disappears, and now, using claude 2.1.289, all AltGr keys work well in Windows Terminal ; maybe a fix in its 1.140.0 update...