Update win32-input-mode to preserve standard keys and signals #23826

Closed
opened 2026-01-31 08:53:38 +00:00 by claunia · 11 comments
Owner

Originally created by @unxed on GitHub (Nov 23, 2025).

Description of the new feature

Description of the new feature / enhancement

I propose a refinement to the win32-input-mode (enabled via ^[[?9001h), originally introduced in spec 4999.

Currently, when this mode is active, all keyboard input is converted into generated CSI sequences (^[[Vk;Sc;Uc;Kd;Cs;Rc_). I request a modification (or a sub-parameter) to make this mode behave as a progressive enhancement, similar to how the kitty keyboard protocol or standard VT behavior works:

  1. Standard printable characters should remain as plain text.
  2. Standard signals (like Ctrl+C) should be sent as signals/bytes (SIGINT/\x03), not as escape sequences.
  3. Only complex keys (which cannot be represented by standard VT, e.g., Ctrl+Space, Shift+Enter, independent modifier presses, KeyUp events) should use the win32-input-mode encoding.

Why is this needed? (The "Bricked Terminal" Problem)

This request is directly motivated by the refusal of shell maintainers (specifically fish-shell) to support the current protocol.

As discussed in fish-shell issue #11877, the current "all-or-nothing" approach creates a critical reliability issue:

"It also appears to send every key in the new encoding... so if it remains turned on (e.g. because of a crash in a program that turns it on), it renders the session unusable." — @faho (fish-shell maintainer)

The Scenario:

  1. A user launches a tool that enables win32-input-mode.
  2. The tool crashes or hangs without properly disabling the mode.
  3. The user is dropped back into the shell.
  4. The terminal becomes unusable. The user cannot type reset to fix the terminal, because the shell receives complex escape sequences instead of the characters r, e, s, e, t. Even Ctrl+C is sent as a sequence, effectively preventing the user from interrupting the hung state via standard means.

Because of this risk, generic shells are unlikely to adopt win32-input-mode in its current form.

Current Adoption vs Potential

The protocol is already valuable and is used by specialized applications like:

  • far2l (Linux port of Far Manager 2)
  • turbo (TUI text editor)

However, wider adoption in the ecosystem (shells like fish, zsh, bash, and other CLI tools) depends on safety. If win32-input-mode sent standard keys as-is, it would allow shells to support rich input scenarios (like Ctrl+Alt+? or Shift+Enter bindings) without the risk of breaking the session in case of a crash.

Originally created by @unxed on GitHub (Nov 23, 2025). ### Description of the new feature ### Description of the new feature / enhancement I propose a refinement to the `win32-input-mode` (enabled via `^[[?9001h`), originally introduced in spec [4999](https://github.com/microsoft/terminal/blob/main/doc/specs/%234999%20-%20Improved%20keyboard%20handling%20in%20Conpty.md). Currently, when this mode is active, **all** keyboard input is converted into generated CSI sequences (`^[[Vk;Sc;Uc;Kd;Cs;Rc_`). I request a modification (or a sub-parameter) to make this mode behave as a **progressive enhancement**, similar to how the [kitty keyboard protocol](https://sw.kovidgoyal.net/kitty/keyboard-protocol/) or standard VT behavior works: 1. **Standard printable characters** should remain as plain text. 2. **Standard signals** (like `Ctrl+C`) should be sent as signals/bytes (`SIGINT`/`\x03`), not as escape sequences. 3. **Only complex keys** (which cannot be represented by standard VT, e.g., `Ctrl+Space`, `Shift+Enter`, independent modifier presses, KeyUp events) should use the `win32-input-mode` encoding. ### Why is this needed? (The "Bricked Terminal" Problem) This request is directly motivated by the refusal of shell maintainers (specifically **fish-shell**) to support the current protocol. As discussed in [fish-shell issue #11877](https://github.com/fish-shell/fish-shell/issues/11877), the current "all-or-nothing" approach creates a critical reliability issue: > "It also appears to send *every* key in the new encoding... so if it remains turned on (e.g. because of a crash in a program that turns it on), it renders the session unusable." — @faho (fish-shell maintainer) **The Scenario:** 1. A user launches a tool that enables `win32-input-mode`. 2. The tool crashes or hangs without properly disabling the mode. 3. The user is dropped back into the shell. 4. **The terminal becomes unusable.** The user cannot type `reset` to fix the terminal, because the shell receives complex escape sequences instead of the characters `r`, `e`, `s`, `e`, `t`. Even `Ctrl+C` is sent as a sequence, effectively preventing the user from interrupting the hung state via standard means. Because of this risk, generic shells are unlikely to adopt `win32-input-mode` in its current form. ### Current Adoption vs Potential The protocol is already valuable and is used by specialized applications like: * [far2l](https://github.com/elfmz/far2l/) (Linux port of Far Manager 2) * [turbo](https://github.com/magiblot/turbo) (TUI text editor) However, wider adoption in the ecosystem (shells like `fish`, `zsh`, `bash`, and other CLI tools) depends on safety. If `win32-input-mode` sent standard keys as-is, it would allow shells to support rich input scenarios (like `Ctrl+Alt+?` or `Shift+Enter` bindings) without the risk of breaking the session in case of a crash.
claunia added the Issue-FeatureNeeds-TriageNeeds-Tag-Fix labels 2026-01-31 08:53:38 +00:00
Author
Owner

@krobelus commented on GitHub (Nov 23, 2025):

time would probably be better spent on implementing the existing kitty protocol (https://github.com/microsoft/terminal/issues/11509)

Standard signals (like Ctrl+C) should be sent as signals/bytes (SIGINT/\x03), not as escape sequences.

not sure about that

@krobelus commented on GitHub (Nov 23, 2025): time would probably be better spent on implementing the existing kitty protocol (https://github.com/microsoft/terminal/issues/11509) > Standard signals (like Ctrl+C) should be sent as signals/bytes (SIGINT/\x03), not as escape sequences. [not sure about that](https://github.com/kovidgoyal/kitty/issues/7961)
Author
Owner

@unxed commented on GitHub (Nov 23, 2025):

Kitty protocol is also far from ideal. Here is some notes why win32 input mode is better:
https://gitlab.gnome.org/GNOME/vte/-/issues/2601#note_2567580

@unxed commented on GitHub (Nov 23, 2025): Kitty protocol is also far from ideal. Here is some notes why win32 input mode is better: https://gitlab.gnome.org/GNOME/vte/-/issues/2601#note_2567580
Author
Owner

@j4james commented on GitHub (Nov 23, 2025):

If win32-input-mode sent standard keys as-is, it would allow shells to support rich input scenarios (like Ctrl+Alt+? or Shift+Enter bindings) without the risk of breaking the session in case of a crash.

As I mentioned in the fish issue, this would not help. The risk they're concerned about is from another app setting win32-input-mode and then crashing. Ironically this would be less of a problem if they actually supported win32-input-mode. But it could probably also be addressed by adding something like \e[?9001l to their prompt sequence.

@j4james commented on GitHub (Nov 23, 2025): > If win32-input-mode sent standard keys as-is, it would allow shells to support rich input scenarios (like Ctrl+Alt+? or Shift+Enter bindings) without the risk of breaking the session in case of a crash. As I mentioned in the fish issue, this would not help. The risk they're concerned about is from _another_ app setting win32-input-mode and then crashing. Ironically this would be less of a problem if they actually supported win32-input-mode. But it could probably also be addressed by adding something like `\e[?9001l` to their prompt sequence.
Author
Owner

@krobelus commented on GitHub (Nov 23, 2025):

But it could probably also be addressed by adding something like \e[?9001l to their prompt sequence.

Hmm maybe. I wonder if this helps real users. (I guess maybe the ones using far2l or turbo in Windows terminal; we haven't heard of it yet).
I think programs like ssh might benefit from doing this too (because connection drop typically leaves the terminal in an inconsistent state), but I'm not sure the ssh discussion established consensus on what to do

@krobelus commented on GitHub (Nov 23, 2025): > But it could probably also be addressed by adding something like \e[?9001l to their prompt sequence. Hmm maybe. I wonder if this helps real users. (I guess maybe the ones using far2l or turbo in Windows terminal; we haven't heard of it yet). I think programs like `ssh` might benefit from doing this too (because connection drop typically leaves the terminal in an inconsistent state), but I'm not sure the [ssh discussion](https://marc.info/?l=openssh-unix-dev&m=172036252230703&w=2) established consensus on what to do
Author
Owner

@j4james commented on GitHub (Nov 23, 2025):

I wonder if this helps real users.

In general maybe, although I think the win32-input-mode case is going to be rare (same with the higher kitty keyboard modes). You'd need to be running an app that's using that mode. That app would then need to crash without restoring things. And the most likely follow up to that would be the user restarting their session and getting on with whatever they were doing. It's just not that big a deal in my opinion. They're going to be more annoyed by the app crash than the state of the shell afterwards.

And personally I'd prefer the terminal itself to have a reset menu to deal with situations like this (I'm sure we already have an issue for that somewhere). I'm just surprised that shells don't also have an option for this themselves, if it's something they're really concerned about. And I don't mean for win32-input-mode specifically - just cleaning the terminal state in general (things like character sets, margins, alt buffer mode, etc.).

But the main point I wanted to make was that these concerns are not what is preventing fish from adding support for win32-input-mode. Even if we already had a bunch of progressive enhancement options like kitty, fish still wouldn't be implementing it, and the potential for the shell being left in an usable state would still exist.

@j4james commented on GitHub (Nov 23, 2025): > I wonder if this helps real users. In general maybe, although I think the win32-input-mode case is going to be rare (same with the higher kitty keyboard modes). You'd need to be running an app that's using that mode. That app would then need to crash without restoring things. And the most likely follow up to that would be the user restarting their session and getting on with whatever they were doing. It's just not that big a deal in my opinion. They're going to be more annoyed by the app crash than the state of the shell afterwards. And personally I'd prefer the terminal itself to have a reset menu to deal with situations like this (I'm sure we already have an issue for that somewhere). I'm just surprised that shells don't also have an option for this themselves, if it's something they're really concerned about. And I don't mean for win32-input-mode specifically - just cleaning the terminal state in general (things like character sets, margins, alt buffer mode, etc.). But the main point I wanted to make was that these concerns are not what is preventing fish from adding support for win32-input-mode. Even if we already had a bunch of progressive enhancement options like kitty, fish still wouldn't be implementing it, and the potential for the shell being left in an usable state would still exist.
Author
Owner

@krobelus commented on GitHub (Nov 23, 2025):

You'd need to be running an app that's using that mode. That app
would then need to crash without restoring things. And the most
likely follow up to that would be the user restarting their session
and getting on with whatever they were doing. It's just not that
big a deal in my opinion. They're going to be more annoyed by the
app crash than the state of the shell afterwards.

I don't necessarily disagree but to play the devil's advocate:
Whereas crashes are expected to be infrequent, ssh connection drops
can be a daily scenario (due to laptop suspend/resume).
If a user is running

bash -> ssh -> some-fancy-app-enabling-keyboard-input-protocols

Then after a disconnect, ctrl-p (to recall the ssh command) may no
longer work, which can be annoying.

It's maybe not a big deal in practice, since "bash -> ssh -> fish"
has had that problem with the kitty protocol for a while and no one
complained. The easy workaround is to run "fish -> ssh -> fish" of course.

Either way, fixing bash would be doable -- bash/libreadline would
need to support a subset of the kitty keyboard protocol,
however (note the chicken-and-egg problem)
they wanted to "wait until more terminals implement this" (https://lists.gnu.org/archive/html/bug-readline/2022-04/msg00010.html).

(To be fair, it may be harder for them to implement the full protocol
because they'd need to come up with a inputrc syntax that supports
kitty key events that may have differing physical and logical keys.)

And personally I'd prefer the terminal itself to have a reset menu
to deal with situations like this (I'm sure we already have an issue
for that somewhere).

yeah, I think at least kitty has a hotkey to reset the VT parser state
(allegedly useful when the OSC/DCS parser is stuck) which probably
also resets terminal modes.

I'm just surprised that shells don't also have
an option for this themselves, if it's something they're really
concerned about.

They do: to not break its child processes, fish un-sets the kitty keyboard mode
before running an external command, and sets it every time it regains control.
It's just that fish OOTB is not aware of the win32 mode today.

And I don't mean for win32-input-mode specifically -
just cleaning the terminal state in general (things like character
sets, margins, alt buffer mode, etc.).

fish resets some TTY flags (see "term_fix_modes()"),
so it's definitely trying to meet such expectations.
Bash doesn't reset anything, which is great for learning/debugging :)

@krobelus commented on GitHub (Nov 23, 2025): > You'd need to be running an app that's using that mode. That app > would then need to crash without restoring things. And the most > likely follow up to that would be the user restarting their session > and getting on with whatever they were doing. It's just not that > big a deal in my opinion. They're going to be more annoyed by the > app crash than the state of the shell afterwards. I don't necessarily disagree but to play the devil's advocate: Whereas crashes are expected to be infrequent, ssh connection drops can be a daily scenario (due to laptop suspend/resume). If a user is running bash -> ssh -> some-fancy-app-enabling-keyboard-input-protocols Then after a disconnect, ctrl-p (to recall the ssh command) may no longer work, which can be annoying. It's maybe not a big deal in practice, since "bash -> ssh -> fish" has had that problem with the kitty protocol for a while and no one complained. The easy workaround is to run "fish -> ssh -> fish" of course. Either way, fixing bash would be doable -- bash/libreadline would need to support a subset of the kitty keyboard protocol, however (note the chicken-and-egg problem) they wanted to "wait until more terminals implement this" (https://lists.gnu.org/archive/html/bug-readline/2022-04/msg00010.html). (To be fair, it may be harder for them to implement the full protocol because they'd need to come up with a inputrc syntax that supports kitty key events that may have differing physical and logical keys.) > And personally I'd prefer the terminal itself to have a reset menu > to deal with situations like this (I'm sure we already have an issue > for that somewhere). yeah, I think at least kitty has a hotkey to reset the VT parser state (allegedly useful when the OSC/DCS parser is stuck) which probably also resets terminal modes. > I'm just surprised that shells don't also have > an option for this themselves, if it's something they're really > concerned about. They do: to not break its child processes, fish un-sets the kitty keyboard mode before running an external command, and sets it every time it regains control. It's just that fish OOTB is not aware of the win32 mode today. > And I don't mean for win32-input-mode specifically - > just cleaning the terminal state in general (things like character > sets, margins, alt buffer mode, etc.). fish resets some TTY flags (see "term_fix_modes()"), so it's definitely trying to meet such expectations. Bash doesn't reset anything, which is great for learning/debugging :)
Author
Owner

@DHowett commented on GitHub (Nov 24, 2025):

Because of this risk, generic shells are unlikely to adopt win32-input-mode in its current form.

FWIW, it was not put forth as a general purpose solution to input coding issues in the terminal ecosystem and we don't expect there to be more than two applications in the course of human history which onboard to using it. 🙂

@DHowett commented on GitHub (Nov 24, 2025): > Because of this risk, generic shells are unlikely to adopt `win32-input-mode` in its current form. FWIW, it was not put forth as a general purpose solution to input coding issues in the terminal ecosystem and we don't expect there to be more than two applications in the course of human history which onboard to using it. 🙂
Author
Owner

@unxed commented on GitHub (Nov 24, 2025):

Because of this risk, generic shells are unlikely to adopt win32-input-mode in its current form.

FWIW, it was not put forth as a general purpose solution to input coding issues in the terminal ecosystem and we don't expect there to be more than two applications in the course of human history which onboard to using it. 🙂

I understand. Starting to support a protocol not originally intended for external applications was a clever solution for us at far2l, enabling full keyboard functionality in MS Terminal right here and now, without waiting for the kitty protocol to be implemented. Perhaps someone else will want to follow our path.

@unxed commented on GitHub (Nov 24, 2025): > > Because of this risk, generic shells are unlikely to adopt `win32-input-mode` in its current form. > > FWIW, it was not put forth as a general purpose solution to input coding issues in the terminal ecosystem and we don't expect there to be more than two applications in the course of human history which onboard to using it. 🙂 I understand. Starting to support a protocol not originally intended for external applications was a clever solution for us at far2l, enabling full keyboard functionality in MS Terminal right here and now, without waiting for the kitty protocol to be implemented. Perhaps someone else will want to follow our path.
Author
Owner

@burtonsys commented on GitHub (Nov 27, 2025):

(Newbie warning: I only just now stumbled upon the microsoft/terminal github repository, and I'm completely unfamiliar with the project, so please accept my apology in advance for stupid questions!)

My question: would this proposal solve my problem?

I run SlickEdit 2.4, a superb Win32 console-mode programmers' text editor (circa 1997!!!), and I love that thing! But my problem is that under Win11 25H2 (26200.7171) the Alt-L key shortcut (which SlickEdit 2.4 uses for "mark-line") is no longer passed through to the editor.

(Alt-L doesn't seem to do anything noticeable, so I don't know why it is blocked.)

In Terminal mode, it's even worse: Alt-L and Alt-U (which SlickEdit 2.4 uses for "unmark") are both blocked.

ChatGPT suggested using the "legacy console," but "Command Prompt" Properties -> Options says "The legacy console is not installed." Apparently there's no way to install it, either.

@burtonsys commented on GitHub (Nov 27, 2025): _(Newbie warning: I only just now stumbled upon the microsoft/terminal github repository, and I'm completely unfamiliar with the project, so please accept my apology in advance for stupid questions!)_ My question: would this proposal solve my problem? I run SlickEdit 2.4, a superb Win32 console-mode programmers' text editor (circa 1997!!!), and I love that thing! But my problem is that under Win11 25H2 (26200.7171) the Alt-L key shortcut (which SlickEdit 2.4 uses for "mark-line") is no longer passed through to the editor. (Alt-L doesn't seem to do anything noticeable, so I don't know why it is blocked.) In Terminal mode, it's even worse: Alt-L and Alt-U (which SlickEdit 2.4 uses for "unmark") are both blocked. ChatGPT suggested using the "legacy console," but "Command Prompt" Properties -> Options says "The legacy console is not installed." Apparently there's no way to install it, either.
Author
Owner

@krobelus commented on GitHub (Nov 29, 2025):

can we close this issue? Looks like this protocol wasn't meant to be used by external consumers,
and the arguments in favor of doing so seem weak and frankly reactionary.
It also doesn't seem like the observations are relevant to any existing consumers.

My question: would this proposal solve my problem?

no. If it's only Alt-l but for all applications then it's likely being intercepted

@krobelus commented on GitHub (Nov 29, 2025): can we close this issue? Looks like this protocol wasn't meant to be used by external consumers, and the arguments in favor of doing so seem weak and frankly reactionary. It also doesn't seem like the observations are relevant to any existing consumers. > My question: would this proposal solve my problem? no. If it's only Alt-l but for all applications then it's likely being intercepted
Author
Owner

@burtonsys commented on GitHub (Nov 29, 2025):

no. If it's only Alt-l but for all applications then it's likely being intercepted

Sorry, krobelus, I don't understand your reply. What is intercepting Alt-L, and how can I get it to stop intercepting Alt-L?

Also, in Terminal, what is intercepting Alt-L and Alt-U, and how can I get it to stop intercepting them?

@burtonsys commented on GitHub (Nov 29, 2025): > no. If it's only Alt-l but for all applications then it's likely being intercepted Sorry, krobelus, I don't understand your reply. **_What_** is intercepting Alt-L, and how can I get it to stop intercepting Alt-L? Also, in Terminal, what is intercepting Alt-L and Alt-U, and how can I get it to stop intercepting them?
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#23826