Skip to content

Instantly share code, notes, and snippets.

@borekb
Created July 29, 2018 14:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save borekb/d36b1d3c4e83514a8d68222d6916a83f to your computer and use it in GitHub Desktop.
Save borekb/d36b1d3c4e83514a8d68222d6916a83f to your computer and use it in GitHub Desktop.
Dealing with tty / pty in MSYS2 shells

Dealing with tty / pty in MSYS2 shells

In my experience, the biggest practical hurdle when running a mix of native and MSYS2 programs is related to tty / pty. I wish I understood perfectly what is going on but at least I think I can explain the problem and what are the options. When I learn more, I'll be happy to update this post.

The problem

When you run a shell of your choice like bash.exe or zsh.exe, you have three main options:

  1. Run it in the mintty terminal.
  2. Run it in Windows console ("cmd.exe").
  3. Run it via ConEmu connector which is roughly equivalent to starting Command Prompt and running conemu-msys2-64.exe C:\msys64\usr\bin\bash.exe --login -i.

mintty is the default in both Git Bash and MSYS2 shells as historically, this used to be a much better experience than using Windows console. The problem with mintty is that it doesn't present itself as a console to native CLI programs which leads to all sorts of issues in practice, for example:

  • docker run -it ubuntu /bin/bash will not work, trying to prepend a Windows path before /bin/bash.
  • npm and yarn will not display colorful outputs.
  • python will refuse to start in interactive mode.
  • gcloud commands asking for input will seemingly hang.

If you have Node.js installed, you can try this:

# mintty
$ node -p -e "Boolean(process.stdout.isTTY)"
false

# Windows console
$ node -p -e "Boolean(process.stdout.isTTY)"
true

The core issue here is that native Windows programs don't think they are running in an interactive console which leads to all the problems above. You'll observe the same if you run your shell through ConEmu connector.

There are two main options what to do about it:

  1. Running a shell from Windows console.
  2. Use winpty.

Option one: Windows console

Windows console ("console host", "conhost") got much better in Windows 10 with colored output, Unicode support, resizable windows, better copy & paste, etc. Microsoft continues to work hard on it so seemingly, avoiding mintty or the connector should be the way to go.

However, after running zsh via Windows console for about a week, I found our that there were too many issues there, for example, colors in my prompt were not working correctly, Yarn and npm were doing some funny path manipulations, @elieux reporeted some issues with mc and text-based user interface apps in general, etc.

In practice, this was too troublesome.

Option two: winpty

Winpty provides pty-like interface for Windows programs. Instead of running <some-program>, you run winpty <some-program>:

$ node -p -e "Boolean(process.stdout.isTTY)"
false

$ winpty node -p -e "Boolean(process.stdout.isTTY)"
true

❗ Use official winpty binaries, not those from MSYS2, see msys2/MSYS2-packages#411 (comment)

Git for Windows even tries to do this for popular binaries automatically so you can add their code to your .bashrc / .zshrc. Also, for any binaries not in that list, just add the aliases manually, like:

alias npm='winpty npm.cmd'
alias yarn='winpty yarn.cmd'
alias gcloud='winpty gcloud.cmd'

Alternatively, if you don't want to rely on aliases, create a small shell script for each binary like this:

#!/bin/bash
winpty "npm.cmd" "$@"

Now, winpty is not without its issues. They are quite subtle and I didn't encounter anything too serious but if you're interested, VSCode maintains a relatively long list of winpty-related issues in their terminal.

Resources

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment