ctrl+space interpreted as ctrl+@ or \x00 in VSCode terminal (and many others)
Have you checked closed issues? (https://github.com/Textualize/textual/issues?q=is%3Aissue+is%3Aclosed) yes
Have you checked against the most recent version of Textual? (https://pypi.org/search/?q=textual) yes
The ask / suggested fix
Interpret ctrl+@ as ctrl+space since that is what most terminals send when you hit ctrl+space.
The bug
Run textual keys in kitty and vscode terminal and press space and ctrl+space. In kitty you correctly get:
Key(key='space', character=' ', name='space', is_printable=True)
Key(key='ctrl+space', character=None, name='ctrl_space', is_printable=False)
but VSCode shows
(Screenshot since vscode doesn't support shift+highlight to bypass mouse interception)
I think ctrl+space is much more likely to be a useful mapping than ctrl+@, so it is probably best to just interpret the latter as the former. Interestingly if I hit ctrl+shift+2 (@ is shift+2 on my keyboard), vscode outputs the same line as ctrl+space, while kitty outputs nothing. Kitty defaults to mapping that to go to window 2, so it is intercepted before reaching textual (ctrl+shift is the default "kitty_mod" to send commands to kitty). If I remove that mapping it will send the following, so there is no way to generate ctrl+@ unless you have a dedicated @ key (or make a weird custom mapping...):
Key(key='ctrl+shift+2', character=None, name='ctrl_shift_2', is_printable=False)
After typing most of this bug up, I also tried xterm, Apple's terminal.app, wezterm and ghostTTY (all on a mac but sshed into linux). ghostTTY behaved identically to kitty (although it sends ctrl+shift+2 by default since it is unmapped), but the rest send ctrl+@ like vscode. If I had to guess, kitty and ghost support the fancy kitty input protocol but the others don't.
Textual Diagnostics
Versions
| Name | Value |
|---|---|
| Textual | 3.5.0 |
| Rich | 14.0.0 |
Python
| Name | Value |
|---|---|
| Version | 3.13.5 |
| Implementation | CPython |
| Compiler | GCC 6.3.0 20170516 |
| Executable | /home/mstearn/.local/share/uv/tools/textual-dev/bin/python |
Operating System
| Name | Value |
|---|---|
| System | Linux |
| Release | 6.14.10 |
| Version | #1 SMP Sat Jun 7 02:45:18 UTC 2025 |
Terminal
| Name | Value |
|---|---|
| Terminal Application | vscode (1.101.2) |
| TERM | xterm-256color |
| COLORTERM | truecolor |
| FORCE_COLOR | Not set |
| NO_COLOR | Not set |
Rich Console options
| Name | Value |
|---|---|
| size | width=214, height=31 |
| legacy_windows | False |
| min_width | 1 |
| max_width | 214 |
| is_terminal | True |
| encoding | utf-8 |
| max_height | 31 |
| justify | None |
| overflow | None |
| no_wrap | False |
| highlight | None |
| markup | None |
| height | None |
We found the following entries in the FAQ which you may find helpful:
Feel free to close this issue if you found an answer in the FAQ. Otherwise, please give us a little time to review.
This project is developed and maintained by Will McGugan. Consider sponsoring Will's work on this project (and others).
This is an automated reply, generated by FAQtory
Update: I got curious and tried alt+space and the results were far more interesting and varied! Again, kitty and ghostTTY were the only ones that handled it correctly as:
Key(key='alt+space', character=None, name='alt_space', is_printable=False)
xterm crashed terminal keys with UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe5 in position 0: invalid continuation byte (it may be misconfigured since I never use it)
vscode and terminal.app output:
wezterm outputs:
Key(key='escape', character='\x1b', name='escape', is_printable=False, aliases=['escape', 'ctrl+left_square_brace'])
Key(key='space', character=' ', name='space', is_printable=True)
Fun!
@Guevaraxxx
ctrl+alt+space is even more of a lost cause. ghostTTY is the only one that correctly handles it. Kitty outputs the same as plain space, VSCode outputs nothing, and I'm not going to bother looking into everyone else...
Please check #6074 as it enables more of the Kitty protocol. I guess for VSCode we need to implement the Kitty protocol in Javascript, but it's a VS code feature not a Textual bug/feature