[BUG] Desktop (Linux/Wayland): chat shortcuts match on physical key code — Ctrl+AltGr+d (= Ctrl+Backspace on Bone/Neo layouts) closes the chat instead of deleting a word
Preflight Checklist
- [x] I have searched existing issues (related: #67522 macOS/Neo 2 "Cmd+V starts a new session", #78002 zoom shortcuts bound to physical US positions, #90761 keyboard meta issue)
- [x] Reproducible on the current release
What's Wrong?
In the desktop app's chat surface (claude.ai loaded inside the Electron shell), keyboard shortcuts are matched on KeyboardEvent.code (physical key position) instead of KeyboardEvent.key. With any layout that moves keys away from their QWERTY positions, a completely unrelated key combination triggers app shortcuts.
Concrete case, German Bone layout (a Neo-family layout, xkb de(bone)), Linux/Wayland:
- Bone puts Backspace on layer 4 of the physical W key (
AltGr+din Bone letters). This is the layout's normal way to type Backspace;Ctrl+AltGr+d= "delete word to the left". - In a chat,
Ctrl+AltGr+dcloses the current chat and lands on the "New chat" screen instead of deleting the word. The composer text is gone. - Plain
Ctrl+Backspaceon the dedicated Backspace key works.
What the browser delivers for the failing combo (logged in a plain page inside the app's own Chromium, where the word is deleted correctly):
keydown key=Backspace code=KeyW keyCode=8 ctrlKey=true altKey=false
beforeinput inputType=deleteWordBackward
So Chromium gets it right; the app-side matcher does not. In the loaded frontend bundle (shared-13-*.js) there is a dedicated check that is only active inside the desktop app:
function JI(e,t){return t.isClaudeApp && e.code==="KeyW" && WI(e,UI("cmd+w"),t.mac??fa())}
and the generic resolver compares e.code !== r.code for every shortcut unless the entry sets matchBy: "key" or "char". Any layout where Ctrl + some function key (Backspace, Delete, arrows, Home/End on a layer) lands on the physical KeyW position hits the "close chat" path. #67522 (Neo 2 on macOS, v sits on physical W → Cmd+V starts a new session) looks like the same code path.
What Should Happen?
Ctrl+AltGr+d (which the OS reports as key="Backspace") should behave like Ctrl+Backspace and delete the previous word. More generally: when event.key is a non-printable key (Backspace, Delete, Arrow*, Home, End, Tab, …), it should never match a letter shortcut, regardless of event.code. Matching by code only makes sense as a fallback for printable keys on non-Latin layouts, and even then key should win when it is itself a plain Latin letter.
Error Messages/Logs
None (no crash). Keydown log above.
Steps to Reproduce
- Linux, KDE Plasma (Wayland), keyboard layout German → Bone (
setxkbmap de bone), or Neo 2 (same layer-4 layout). - Open the desktop app, open any chat, type a few words into the composer.
- Press
Ctrl+AltGr+d(Bone letter d = physical W; AltGr+d is Backspace on this layout). - Observe: chat closes, app shows "New chat", composer content lost. Expected: previous word deleted.
Also reproducible without a special layout: any layout, Ctrl + physical W should not be treated as Ctrl+W when the OS reports a different key for it.
Claude Model
n/a
Is this a regression?
Unknown
Last Working Version
n/a
Claude Code Version
Desktop app 1.49585.0 (/usr/lib/claude-desktop/version 44.2.0), bundled CLI 2.1.263
Platform
Linux (native Wayland, no XWayland)
Operating System
TUXEDO OS 24.04 (Ubuntu Noble base), KDE Plasma 6.6.5, kernel 7.0.0
Terminal/Shell
n/a (chat surface, not the terminal)
Additional Information
Workaround I use: a keyd rule that rewrites Ctrl+AltGr+W/R/A/S/D/F/G at the evdev level into real Ctrl+Backspace/Delete/Home/Left/Down/Right/End keycodes, so the app sees code=Backspace. Not something most users will find.