TTY Detection

As a concept, standard I/O is decoupled from terminals and devices. However, it can be useful to know whether a program is directly connected to a terminal or whether its I/O is being redirected.

We can check with the isTTY flag on each I/O channel.

For instance, let's try the following command:

$ node -p "process.stdin.isTTY" 
true
The -p flag
The -p flag will evaluate a supplied string and output the final result. There's also the related -e flag which only evaluates a supplied command line string, but doesn't output its return value.

We're running node directly, so our STDIN is correctly identified as a TTY input.

Now let's try the following:

$ echo "hi" | node -p "process.stdin.isTTY" 
undefined

This time isTTY is undefined. This is because our program is executed inside a shell pipeline. It's important to note that isTTY is undefined and not false, as this can lead to bugs (for instance, when checking for a false value instead of a falsey result).

The isTTY flag is undefined instead of false in the second case because the standard I/O channels are internally initialized from different constructors depending on the scenario. So when the process is directly connected to a terminal, process.stdin is created using the core tty module's ReadStream constructor, which has the isTTY flag. However, when I/O is redirected, the channels are created from the net module's Socket constructor, which does not have an isTTY flag.

Knowing whether a process is directly connected to a terminal can be useful in certain cases – for instance, when determining whether to output plain text or text decorated with ANSI escape codes for coloring, boldness, and so forth.