Repository navigation
[Discussion] System.Console re-design #52374
Description
The initial design of System.Console was mainly driven by Windows OS capabilities and available APIs.
When .NET became cross platform, a number of issues arose (click on the details button below to see the full list) as there was no good way of mapping some Windows-specific concepts to Unix. A good example are all Console.Window* APIs: on Unix the Window is owned by the Terminal app, the .NET Console App has no control over it.
The current design makes no distinction between Console and Terminal, which is also a source of plenty of issues (mostly for apps that have redirected output).
Moreover, System.Console is a static class and there is no common abstraction that would allow not only for testing but also for integrating projects like spectre.console and System.CommandLine.Rendering.
By creating this issue I would like to start a public and transparent discussion about what is wrong with the current design of System.Console and how we could fix that. Based on the results of this discussion, I would like to create a proposal for .NET 7.
cc @jonsequitur @KathleenDollard @patriksvensson @colombod @Keboo @HowardvanRooijen @daxian-dbw
Details
Console.ReadKey:Console.ReadKeyreturns incomplete information for some key sequences on Linux Console.ReadKey returns incomplete information for some key sequences on Linux #802 (.NET 6)System.ConsoleKeyInfocan not handle Unicode surrogate pair and Emoji Sequences System.ConsoleKeyInfo can not handle Unicode surrogate pair and Emoji Sequences #27828Console.ReadKey()doesn't work for keys from the numeric keypad in the PuTTY ssh clientConsole.ReadKey()doesn't work for keys from the numeric keypad in the PuTTY ssh client #25735- [Windows Terminal]
Console.KeyAvailablecauses the next Unicode character input 'EN DASH' to be skipped in console [Windows Terminal]Console.KeyAvailablecauses the next Unicode character input 'EN DASH' to be skipped in console #38966 - .NET 5 fails to read the HOME key on ubuntu16.04 .NET 5 fails to read the HOME key on ubuntu16.04 #44621
- Console.ReadKey and pressing SHIFT+END returns invalid escape sequence on WSL/Ubuntu Console.ReadKey and pressing SHIFT+END returns invalid escape sequence on WSL/Ubuntu #45597
- System.Console.ReadKey fails in MSYS' console mintty System.Console.ReadKey fails in MSYS' console mintty #49210
- Let System.ConsoleKeyInfo able to represent keypress in the Unicode world Let System.ConsoleKeyInfo able to represent keypress in the Unicode world #51085
Console.ReadKeythrows in unexpected circumstances Console.ReadKey throws in unexpected circumstances #59059- Support language input keys Support language input keys #63034
- Redirection:
- console redirection is broken console redirection is broken #22314
- Don't dup stdin & stderr as this can break some std io redicection code Don't dup stdin & stderr as this can break some std io redicection code #25394
- Console.CursorLeft, Console.CursorTop, Console.WindowWidth, Console.WindowHeight and Console.WindowTopLeft doesn't throw an IOException for invalid values on Windows 7 x86 when Input is redirected Console.CursorLeft, Console.CursorTop, Console.WindowWidth, Console.WindowHeight and Console.WindowTopLeft doesn't throw an IOException for invalid values on Windows 7 x86 when Input is redirected #43138
- Colors:
- Bright console colors don't work correctly on Linux Bright console colors don't work correctly on Linux #23241
- Implement a way to enable color in console even when the output is redirected Implement a way to enable color in console even when the output is redirected #33980
- Overload Console.Write and Console.WriteLine to take ConsoleColor as a parameter Overload Console.Write and Console.WriteLine to take ConsoleColor as a parameter #39746
- Developers using Console can employ VT/ANSI APIs (eg to use embedded color codes) Developers using Console can employ VT/ANSI APIs (eg to use embedded color codes) #44513 (.NET 6)
- Add overloads to Console.Write that also take a ConsoleColor parameter ([API Proposal]: Add overloads to
Console.Writethat also take aConsoleColorparameter #61731) - Console.Foreground does not correctly set the color in every Terminal (Console.Foreground does not correctly set the color in every Terminal #62186)
- Terminal:
- MacOS 10.13.6 Console.SetWindowSize() exception MacOS 10.13.6 Console.SetWindowSize() exception #27216
- Terminal hardware is always left in application mode (keypad_xmit) after running a console program Terminal hardware is always left in application mode (keypad_xmit) after running a console program #27626
- Console.Clear() doesn't clear the scrollback buffer on Unix-like platforms Console.Clear() doesn't clear the scrollback buffer on Unix-like platforms #28355
- Setting Console.CursorVisible property does not change visibility in Linux Setting Console.CursorVisible property does not change visibility in Linux #31063
- Cannot use left/right arrow keys to edit text in Console.ReadLine on Unix Cannot use left/right arrow keys to edit text in Console.ReadLine on Unix #38051
- System.Console.Read() needlessly changes terminal settings on linux System.Console.Read() needlessly changes terminal settings on linux #49129
- Console issues with multithreaded c# app only when run on Linux Console issues with multithreaded c# app only when run on Linux #49301
- Encoding:
- Changing console's OutputEncoding on linux to unicode generates garbage Changing console's OutputEncoding on linux to unicode generates garbage #29735
- Consider changing the default console encoding on Windows to UTF-16 Consider changing the default console encoding on Windows to UTF-16 #31466
- Console.OutputEncoding by default returns a wrong value on Windows Nano Server Console.OutputEncoding by default returns a wrong value on Windows Nano Server #42959\
- Console UTF-8 input is misbehaving on Windows Console UTF-8 input is misbehaving on Windows #43295
Console.CancelKeyPress:- Third party code may remove cancel keypress handler Third party code may remove cancel keypress handler #30464
- Setting Console.TreatControlCAsInput to true causes text to be removable Setting Console.TreatControlCAsInput to true causes text to be removable #44667
- .NET 5 apps can no longer intercept SIGINT signals (receive CancelKeyPress events) when running under Docker .NET 5 apps can no longer intercept SIGINT signals (receive CancelKeyPress events) when running under Docker #51221
- Other:
- FreeBSD: System.Console is not working right FreeBSD: System.Console is not working right #23653
- Console.Write prints a new line on iOS Console.Write prints a new line on iOS #36440
- Console.In.Peek() always returning EOF after the first read line on Windows Console.In.Peek() always returning EOF after the first read line on Windows #40735
- Console.KeyAvailable throws when input isn't redirected on Windows 7 x86 Console.KeyAvailable throws when input isn't redirected on Windows 7 x86 #43015
- "System.UnauthorizedAccessException: Access to the path is denied." from Console.WriteLine on Ubuntu 20.10 "System.UnauthorizedAccessException: Access to the path is denied." from Console.WriteLine on Ubuntu 20.10 #48654
- Performance:
Console.OpenStandard*few times slower on Linux Console.OpenStandard* few times slower on Linux #31396
- New APIs:
- We need a cross-platform way to detect key-down state We need a cross-platform way to detect key-down state #24314
- Enhance Console.ReadLine() to return at Tab Enhance Console.ReadLine() to return at Tab #800
- Add API for detecting broken pipe when write to stdout(or stderr) Add API for detecting broken pipe when write to stdout(or stderr) #30540
- Proposal: Async Console I/O APIs Proposal: Async Console I/O APIs #299
- Test issues:
- [mono] Test failed on windows: WindowAndCursorProps.Title_Set_Windows [mono] Test failed on windows: WindowAndCursorProps.Title_Set_Windows #34454
- System.Console tests failing on iOS System.Console tests failing on iOS #36878
- System.Console.Tests fail on Android System.Console.Tests fail on Android #37465
- CancelKeyPressTests.HandlerInvokedForSigQuit test failing on OSX in CI CancelKeyPressTests.HandlerInvokedForSigQuit test failing on OSX in CI #38998
- Docs:
- System.Console: Backport MS Docs documentation to triple slash System.Console: Backport MS Docs documentation to triple slash #48959
Activity
adamsitnik commentedon May 6, 2021
@mdh1418 @MaximLipnin is there any chance that you could share your experience from #41184 #50931 ?
mdh1418 commentedon May 6, 2021
@adamsitnik The work in #41184 and #50931 was primarily done to leverage the platform compatibility analyzer and warn users when a particular API was unsupported on the specific platforms. I believe we had taken note of which APIs failed with
PlatformNotSupportedExceptionwhen running library tests onBrowser-wasmAndroidand alsoiOS+tvOS(which also hadPlatformNotSupportedExceptionforSystem.ConsoleAPIs, and we proceeded to mark those APIs with the Unsupported attributephillip-haydon commentedon May 7, 2021
Microsoft needs to give @patriksvensson a ton of money and replace with spectre.
HowardvanRooijen commentedon May 7, 2021
@phillip-haydon If you notice, Patrik is CC'd on the first message in the thread, because we've been having fortnightly calls for many months on the subject! The point of this thread is to mobilise "an army of the willing" who want to see these improvements invested in, and delivered! My original request was "please can we interop between System.CommandLine and Spectre?" 😁
phillip-haydon commentedon May 7, 2021
I saw, I'm just totally blown away at spectre, been following it on twitter, we need to give Patrik more recognition that he's built something amazing :D (and the contributors to the project too)
HowardvanRooijen commentedon May 7, 2021
100% I've said that Spectre delivers the "high level productivity API", that enables me to build impressive things quickly. It's like having the WebControls / WinForm Controls / WPF Components for the CLI, but there are also the lower-level APIs that are needed to deliver that experience consistently across all the platforms that .NET Supports. Hence my tagline of:
Spectre.Console + System.CommandLine = ❤
maloo commentedon May 7, 2021
Please make sure it works great with https://github.com/migueldeicaza/gui.cs
adamsitnik commentedon May 7, 2021
@migueldeicaza would you like to provide some feedback based on your experience with building https://github.com/migueldeicaza/gui.cs?
23 remaining items
deeprobin commentedon Apr 14, 2022
@hamarb123 I think that bug does relate to the current API. Can you create a new Issue for this?
I am not sure if this is possible. I guess this is something that belongs to the
conhoston windows.But there are ANSI control sequences for scrolling 1 (but these are not supported in
ANSI.SYS= no DOS-support):<ESC>[r<ESC>[{start};{end}r<ESC>D<ESC>MFootnotes
https://www.cse.psu.edu/~kxc104/class/cmpen472/11f/hw/hw7/vt100ansi.htm ↩
zadjii-msft commentedon Apr 14, 2022
FWIW, no, controlling the scrollbar is not something that's broadly possible with VT/escape sequences. The "scroll up/down" sequences are used for shifting the contents within the active buffer (the "viewport" at the bottom of the scrollback), and account for things like scroll margins, but they don't move the viewport into scrollback.
Not all terminals have support for scrollback. There have been a few attempts across the ecosystem to try and roll one-off sequences for controlling the position of the viewport, but those aren't widely implemented (to the best of my knowledge).
hamarb123 commentedon Apr 14, 2022
Thanks, I tried some of those sequences and none of them scrolled back into the scroll-back on macOS.
I will make an issue for the macOS clear function as well - thanks.
webczat commentedon Apr 14, 2022
Well what I noticed was mostly things like Read/ReadKey. windows is the os where you can just ReadKey where on unixes it requires switching back and forth between terminal canonical mode, or what is done here, just staying in non canonical mode, so a dotnet console app, even a simple one reading lines, doesn't kinda feel native. Even though the fact itself that you can just ReadKey without doing os specific things is also useful.
I am wondering, if a new api in any shape appears, will Console still be shown by default for simple things like WriteLine?
hamarb123 commentedon Apr 14, 2022
That's another good point @webczat, something like ReadLine doesn't even let you press left and right to move the cursor - I've not seen any other console utility that does this on macOS (except things like vi where it's intentional in certain contexts) - also this doesn't mean they don't exist, I just haven't experienced them.
webczat commentedon Apr 14, 2022
Well generally it's exactly the canonical vs non canonical mode. in canonical mode (default) dotnet is not supposed to handle things character by character, just ReadLine should read from terminal until newline, as only full lines are sent to it. In case of non canonical each character is sent and everything including ^u and ^k keystrokes and other such things, backspace etc needs to be directly handled by the program.
I am on linux BTW.
hamarb123 commentedon Apr 16, 2022
#28355 - seems like I've commented here before also
BDisp commentedon Jan 14, 2023
adamsitnik commentedon Jan 16, 2023
@BDisp please create a new issue, this thread is dedicated to Console re-design
xoofx commentedon Jan 4, 2026
Hey, happy new year!☺️
I've been following this issue because I ran into the same "gap" in System.Console: it's great for simple CLI I/O, but once you want to build a real TUI (or even a robust CI-friendly CLI), you quickly end up re-implementing terminal concepts that aren't really modeled in the BCL API surface.
That's why I wrote two libraries:
XenoAtom.Ansi: a focused ANSI/VT layer (tokens, parsing/decoding, style model). It provides building blocks like an ANSI tokenizer/decoder and a style/color model that understands terminal concepts such as "default" colors, OSC sequences, etc.
Repo: https://github.com/XenoAtom/XenoAtom.Ansi
XenoAtom.Terminal: a modern, Console-like API that keeps the ergonomics of System.Console, but adds terminal-native features needed by TUIs/CLIs: a unified async input event stream (keys/mouse/resize/paste), scoped state restoration (raw/cbreak, alternate screen, cursor visibility…), markup/styling on top of ANSI, clipboard integration, automatic CI color term aware detection, and testable backends (virtual + in-memory).
Repo: https://github.com/XenoAtom/XenoAtom.Terminal
In practice, the biggest missing pieces in System.Console for this space are:
I'm not suggesting the runtime should adopt these libraries, but they might be useful data points for API design discussions here: they show what terminal apps end up needing today, what developers expect ergonomically (Console-like but richer), and where portability issues show up (Windows vs Unix vs CI vs redirected output).
I plan to write a higher-level TUI on top of
XenoAtom.Terminalif folks want to follow more this initiative. ✨Hope it helps!
patriksvensson commentedon Jan 4, 2026
@xoofx You should read the source code to Spectre.Console, because it does indeed support:
About the other points. I would have wished that you brought this up with us so we could have addressed that feedback.
xoofx commentedon Jan 4, 2026
Hey @patriksvensson - thanks for the reply. You're right: I should have explicitly mentioned Spectre.Console in my post, and clarified why I ended up building XenoAtom.Ansi/XenoAtom.Terminal instead of trying to push these ideas into Spectre.
I've used Spectre.Console in a few projects and genuinely liked it. The reason I didn't bring this up earlier isn't because I wanted to "compete" or take over, it's more that the direction I wanted to explore would likely have required changes that are pretty invasive for an established, successful project:
That would have meant significant design discussions and potentially breaking changes, and I didn't want to burn Spectre's team time (or mine) on something you might not want to take Spectre.Console toward.
I see XenoAtom.Terminal with distinct goals rather than a replacement for Spectre.Console. Spectre is rightly popular and covers a broader set of UI scenarios; mine will likely stay niche because of my scenarios.
patriksvensson commentedon Jan 4, 2026
@xoofx We’ve actually been working on a similar push as well:
https://github.com/spectreconsole/terminal
(our first attempt at a terminal library inspired by Cathode; it’s now in read-only mode)
https://github.com/spectreconsole/spectre.tui
(a low-level library for building fast TUI applications)
We also plan to do much of what you’ve done with your Ansi library, as well as create a unified abstraction layer for the terminal with terminfo integration (and shared primitives).
That’s why I mentioned that I would have liked you to bring this up with us earlier (since you mentioned Spectre.Console in this issue). I’m not opposed to you creating a library or anything like that, but I think there could be a lot of synergy between our respective efforts.
xoofx commentedon Jan 4, 2026
Yep, I actually tested Cathode too (and opened an issue there a while back), I liked many things there as well (but also many things were not aligned with what I was looking for).
Spectre.tui is a great initiative! I've worked on UI frameworks before (not terminal-based, D3D12/Vulkan-based), and part of the reason I started
XenoAtom.Terminalis that I want to apply some of those lessons to a terminal stack and explore a direction that's likely a bit different from what existing frameworks do.On the synergy point: I completely agree, and I'd genuinely like that. One reason I usually don't try to bring these ideas upstream earlier is practical: spare time is so scarce, and for hobby work I tend to bias toward "ship code" over "align on process". For example, I developed
XenoAtom.AnsiandXenoAtom.Terminalduring my single week of holidays over Christmas; there's no way I could have achieved that pace inside an existing, well-established project where changes typically require more discussion, consensus-building, conventions, and trade-offs. Starting fresh let me get something up and running quickly that I can now iterate on.This discussion I think is a good place to share our initiatives and ideas, as I just did. So we are actually doing a bit of that synergy already!☺️
patriksvensson commentedon Jan 4, 2026
@xoofx Awesome! Let's move this discussion to Mastodon or similar before the whole issue gets locked 😄