The terminal, the console and the shell - what are they?

Published on 2021-01-13. Modified on 2024-03-14.

The other day, as I was going through some of my old notes, I stumbled upon something I had written about the console, the terminal and the shell on UNIX-like operating systems. I have decided to rewrite these notes in order to share them here on my website. So without further ado we will now stroll down memory lane and take a quick look at the origins of the Unix terminal and shell. And I will also give my advice to new users on Linux or BSD regarding the choice of terminal emulator and shell.

Table of contents

The terminal and the console

Early computers where huge machines that consisted of multiple cabinets, e.g. one cabinet for the CPU, one or more cabinets for tape drives, one cabinet for each disk drive, one cabinet for a punched card reader and one cabinet for a high speed printer. The image below is a Univac 9400 system from 1967 consisting of several cabinets.

A Univac 9400 Mainframe
A Univac 9400 mainframe computer.

The "console" was the "control console". In the pictures below is a "UNIVAC 1" control console and a "UNIVAC 2" control console.

UNIVAC 1 control console
A UNIVAC 1 control console.

UNIVAC 2 control console
A UNIVAC 2 control console.

The word terminal comes from the Latin "terminus", meaning "an end, a limit, boundary line", indicating that it's the terminating end or "terminal" end of a communications process. You will sometimes hear the description "a dumb terminal" when referring to a text-based environment where the computer is just taking input and showing text while the real work happens at the other end, typically in a mainframe.

The teleprinter or TTY was the first kind of terminal. Rather than a monitor you would have a literal typewriter in front of you. When you typed on it, you would see the text on a piece of paper and that text would be send to the computer. When the computer replied, you would see the typewriter print on the paper. Some models could also be used to create punched tape for data storage (either from typed input or from data received from a remote source) and to read back such tape for local printing or transmission.

In the picture below is a Teletype 33 ASR Teleprinter. It was introduced in 1963 as an electro-mechanical teleprinter and it was one of the most popular terminals in the communications industry. The ASR stands for Automatic Send and Receive. The ASR 33 had a built-in punched tape reader and tape punch which allowed the user to save programs.

33 ASR Teleprinter
A Teletype Model 33 ASR teleprinter, usable as a terminal.

If you're interested I can highly recommend that you take a look at Charles Baetsen's Hobby Page as he has a wealth of information about the Teletype 33 ASR in the form of both user manuals, installations manuals and videos.

In the picture below Ken Thompson (sitting) and Dennis Ritchie (standing) is using a 33 ASR teleprinter connected to a PDP-11, the picture is from 1972.

Ken Thompson and Dennis Ritchie
Ken Thompson and Dennis Ritchie using a 33 ASR teleprinter.

Later, as computers became much smaller, it was possible to integrate multiple components into one single unit, with both a video monitor and a keyboard put together inside it, and the "console" now became more or less synonymous to the "terminal". Both the "console" and the "terminal" now referred to the physical video terminal that had replaced both the teleprinter and the old control console.

The video terminal provides a way for the kernel and other processes to send text output on the monitor to the user, and to receive text input from the user via the keyboard.

The VT100 is a video terminal, introduced in August 1978 by Digital Equipment Corporation (DEC). It was one of the first terminals to support ANSI escape codes for cursor control and other tasks, and added a number of extended codes for special features like controlling the status lights on the keyboard. This led to rapid uptake of the ANSI standard, becoming the de facto standard for terminal emulators.


The VT220 is an ANSI standard video terminal introduced by Digital Equipment Corporation (DEC) in November 1983. The VT240 added monochrome vector graphics support to the base model, while the VT241 did the same in color. The 200 series replaced the VT100 series. Among its major upgrades was a number of international character sets, as well as the ability to define new character sets, and a much lighter keyboard.


Today, in the software world, "console" and "terminal" has become completely synonymous.

The virtual terminal

A virtual terminal or virtual console is a program that simulates a physical terminal. For example, both the Linux kernel and the BSD kernels support virtual terminals - terminals that are logically separate, but which access the same physical keyboard and monitor.

The virtual terminal gives the impression that several independent terminals are running concurrently. Each virtual terminal can be logged in with a different user and it can run its own shell and have its own font settings. The virtual terminals each use a device /dev/ttyX, and you can switch between them by pressing Alt+Fn (where n is equal to the virtual terminal number, beginning with 1).

The terminal emulator

Emulation refers to the ability of a computer program to emulate, i.e. imitate, another program or device. A terminal emulator is a computer program that emulates a physical terminal within some other display architecture, such as the X Window System.

Many different terminal emulators have been developed such as the VT52, VT100, VT220, VT320, IBM 3270/8/9/E, IBM 5250, and many others.

The terminal emulator takes the input you type at the keyboard and convert it to ASCII characters which it sends to the shell, or to a program running under the shell (more about the shell later). The terminal emulator also takes the stream of output characters from the various programs you run via the shell and displays them on the monitor.

The purpose of the terminal emulator is to allow access to the command line while working in a graphical user interface, such as the X Window System. Since the shell is "expecting" to interface with a human through a terminal, and we don't use a physical terminal while in a graphical environment, we need the terminal emulator.

You can see what terminal types are available on most Linux distributions by running (the path may be different on your system):

$ ls /lib/terminfo/*

On OpenBSD it's:

$ ls /usr/share/terminfo/*


xterm was originally written as a stand-alone terminal emulator for the VAXStation 100 (VS100) by Mark Vandevoorde, a student of Jim Gettys, who worked at DEC's Cambridge Research Laboratory. It became clear that xterm would be more useful as part of X Window System than as a standalone program, so it was retargeted to the X Window System.

The xterm program is the default terminal emulator for the X Window System. It provides DEC VT102/VT220 features and other selected features from higher-level terminals such as VT320, VT420 and VT520. It also provides Tektronix 4014 emulation for programs that cannot use the window system directly. If the underlying operating system supports terminal resizing (for example, the SIGWINCH signal in systems derived from 4.3bsd), xterm will use the facilities to notify programs running in the window whenever it is resized.

Around 1996 the main line of development shifted to the XFree86 implementation of the X Window System and xterm is now maintained by Thomas Dickey, who is also the current lead developer of Lynx, a popular customizable text-based web browser.

Early versions of xterm emulated the VT102 and Tektronix 4014. Later versions added control sequences for DEC and other terminals such as:

As with most X applications, xterm can be customized via global X resources files (e.g. /usr/lib/X11/app-defaults/XTerm), per-user resource files (e.g. ~/.Xresources), or command-line arguments. Most of the command-line options correspond to resource settings, as noted in the xterm manual page.

While the name of the program is xterm, the X resource class in ~/.Xresources is XTerm, e.g.:

XTerm*utf8: 1

The xterm manual page provides a full list of features and options.

xterm is still being actively developed, it works really great across many different systems, it has extremely low input latency, it has many hidden gems and it is my favorite terminal emulator! For that reason I'm going to share some settings you can use in your ~/.Xresources file:

XTerm*faceName: "DejaVu Sans Mono"
XTerm*faceSize: 12
XTerm*renderFont: true
! Dynamically change font size with CTRL+SHIFT+PageUp/PageDown
XTerm*faceSize1: 12
XTerm*faceSize2: 14
XTerm*faceSize3: 16
XTerm*faceSize4: 18
XTerm*faceSize5: 20
XTerm*faceSize6: 22
XTerm*utf8: 1
XTerm*termName: xterm-256color
XTerm*borderWidth: 0
XTerm*autohint: true
XTerm*backarrowKey: false
XTerm*bellIsUrgent: false
XTerm*cursorBlink: false
XTerm*ScrollKey: true
! Fix ALT key (check in mc with Alt+h)
XTerm*metaSendsEscape: true
XTerm*eightBitInput: false
XTerm*ttyModes: erase ^?
XTerm*fastScroll: true

! I like a lot of scrollback.
XTerm*saveLines: 100000

! Use CLIPBOARD by default.
XTerm*selectToClipboard: true
! Hack xterm to add selection to both PRIMARY and CLIPBOARD.

! xterm defines a whole suite of "actions" for manipulating the terminal e.g.
! copy-selection(), hard-reset(), scroll-back(), etc. These actions can be
! mapped to mouse/key combinations using the translations resource.
! Normally, selected text is stored in PRIMARY, to be pasted with Shift+Insert
! or by using the middle mouse button. With these settings you can use
! CTRL+SHIFT+v/c and you can make Xterm copy to clipboard so that you can use
! CTRL+v in GUI applications.
XTerm*translations: #override \n\
Shift Ctrl <Key>Prior: larger-vt-font() \n\
Shift Ctrl <Key>Next: smaller-vt-font() \n\
Shift Ctrl <Key>C: copy-selection(CLIPBOARD) \n\
Shift Ctrl <Key>V: insert-selection(CLIPBOARD) \n\
<Key>BackSpace: string(0x7f) \n\
<Key>Delete: string(0x1b) string("[3~")

! Theme.
#include ".dotfiles/xresource-themes/ubuntu.Xresources"

Last, but not least, many people become surprised when they discover that xterm has a menu.


st is a simple terminal implementation for Xorg developed by the suckless project. It is intended to serve as a lightweight replacement for xterm.

st currently supports:

Configuration of st is done by manually editing the config.h file and then recompiling st. Because st is very small it compiles very quickly, even on something like a Raspberry Pi. The configuration file is very well documented and most issues are answered in the FAQ.


Alacritty is an open-source GPU accelerated terminal emulator written in Rust for Linux, BSD, macOS and Windows. Alacritty focuses on performance and simplicity.

Alacritty supports scrollback, truecolor, copy/paste, opening URLs by clicking with the mouse, custom key bindings, and more.

Alacritty is configured by editing its configuration file alacritty.yml that contains documentation for all available fields. The GitHub releases page for Alaritty contains a alacritty.yml file for each release that can be used as a boilerplate.

Alacritty does not create the alacritty.yml file for you, but it looks for one in the following locations:

Other terminal emulators

Many other terminal emulators exist. This is a short list of some of them.

What terminal emulator should I use?

If you're new to the world of UNIX-like operating systems you maybe have run into some of the more "fanatical" people in the community telling you that this or that terminal emulator is bad, bloated, slow, outdated, or something else. The fact is that unless you find yourself in a rare edge case, it generally doesn't matter what terminal emulator you use.

Even though xterm is considered bloated, because it contains tons of code that is able to emulate strange and outdated terminals, it is still one of the terminal emulators with the lowest input latency and it is very customizable.

However, terminals such as the GNOME terminal, Konsole and the Xfce terminal are considered more user friendly by some as they can be easier to setup and manage. They also have very good out-of-the-box integration to the desktop system or window manager they support and they add many features that can make it easier to use the terminal and be productive in the X window environment.

My advice is that you try out some of the different terminal emulators and then use the one that gets most "out of your way" and that makes you the most productive. If you have to spend hours getting basic functionality working because you're dealing with some exotic or outdated terminal, then that's just not worth it.

One point worth mentioning is that if you depend on the speed of your terminal emulator to run your shell scripts faster, I recommend that you consider using something other than a shell script. Shell scripts are not really something you deploy when speed matters a lot.

Terminal multiplexer

A terminal multiplexer can be thought of as a console based version of a graphical window manager, or as a way of putting virtual terminals into any login session. It is a wrapper that allows multiple terminal based programs to run at the same time, and it provides features that allow the user to use the programs within a single interface productively. This enables some of the following features: persistence, multiple windows, and session sharing.

tmux and GNU Screen are two popular terminal multiplexers for Linux and BSD.

tmux vs GNU Screen

Theo de Raadt, the founder and project leader for OpenBSD, was impressed with the security of the tmux design:

The most impressive thing about tmux, in my view, is how frustrating the code audit was. In 2 hours, I found only one or two nits that had very minor security consequences. It was not accepted into the tree based on license alone. It is high quality code.

In terms of functionality, screen and tmux both perform similarly and offer the same main features. However, it is the way you access those features that is very different. tmux offers incredibly flexible scripting capabilities.

The environment variable TERM

The environment variable TERM tells applications the name of a terminal description to read from the terminfo database (see man terminfo). Each description consists of a number of named capabilities which tell applications what to send to control the terminal. For example, the cup capability contains the escape sequence used to move the cursor up.

You can read more about TERM in the manual page for your operating system (see man term).

Escape sequences

ANSI escape sequences are a standard for in-band signaling to control cursor location, color, font styling, and other options on video text terminals and terminal emulators. Certain sequences of bytes, most starting with an ASCII escape character and a bracket character, are embedded into text. The terminal interprets these sequences as commands, rather than text to display verbatim.

An escape sequence is a combination of characters that has a meaning other than the literal characters contained therein. It is marked by one or more preceding (and possibly terminating) characters.

As mentioned above, the VT100 terminal implemented the more sophisticated ANSI escape sequences standard for functions such as controlling cursor movement, character set, and display enhancements.

ANSI sequences were introduced in the 1970s to replace vendor-specific sequences and became widespread in the computer equipment market by the early 1980s. They are used in development, scientific, commercial text-based applications as well as bulletin board systems to offer standardized functionality.

Although hardware text terminals have become increasingly rare in the 21st century, the relevance of the ANSI standard persists because a great majority of terminal emulators and command consoles interpret at least a portion of the ANSI standard.

The shell

The operating system is the interface between the user and the hardware. It performs a variety of tasks including controlling hardware devices, file handling, memory management, application process management and much more.

The kernel is the "core" of the operating system that controls and handles all the tasks of the system while the shell is the "interface" that provides users access to communication with the kernel.

A shell process is the program that prompts you for input, takes your commands, and runs them for you. It is a computer program that serves as a command-line interpreter. The shell implements a read-eval-print loop (REPL).

The most generic sense of the term "shell" means any program that users employ to type commands. A shell hides the details of the underlying operating system and manages the technical details of the operating system kernel interface, which is the lowest-level, or "inner-most" component of most operating systems.

When you login to your UNIX-like operating system you are located in the shell. What you see is the input prompt. You enter commands at this input prompt and the shell acts as a "command interpreter". The shell takes each command and passes it to the operating system kernel to handle. The shell then parses the result of this action back to the terminal.

The shell is both an interactive command language and a scripting language, and is used by the operating system to control the execution of the system using shell scripts. The shell exposes the operating system's services to a human user or other programs.

Operating system shells use either a command-line interface (CLI) or graphical user interface (GUI), depending on a computer's role and particular operation.

It is named "a shell" because it is the outermost layer around the operating system.

The shell knows nothing about displaying characters on the monitor or about handling input keystroke codes from the keyboard - that is up to the hardware and software that is implementing the terminal. That is why we interact with the shell using the terminal, however, direct operation via serial hardware connections or Secure Shell are common for server systems. All Unix shells provide filename wildcarding, piping, here documents, command substitution, variables and control structures for condition-testing and iteration.

A shell script is a computer program run by the shell. Instead of direct user input via the keyboard the shell script basically contains a list of such input. This means that you can create a "recipe" of the commands you wish to run and then have the shell perform these commands automatically. One benefit of such a script is that you can reuse it across multiple systems, and you can also save it for later repeated usage.

Because the shell typically also provide different control structures for condition-testing, iteration, variables and other programming related functionality the shell script is considered to be a scripting language.

Typical operations performed by shell scripts include program execution and file manipulation. A script which sets up the system environment, runs programs, and does any necessary cleanup, logging, etc. is typically called a wrapper script.

The type of shell, which may be customized for each user, is typically stored in the user's profile, for example in the local /etc/passwd file or in a distributed configuration system such as NIS or LDAP. However, the user may execute any other available shell interactively.

On computers with a windowing system, such as Microsoft Windows or macOS, some users may never use the shell directly. On Unix systems, the shell has historically been the implementation language of system startup scripts, including the program that starts a windowing system, configures networking, and many other essential functions. However, some system vendors have replaced the traditional shell-based startup system (init) with different approaches, such as systemd.

Maybe you haven't used the shell before, and maybe you're accustomed to interact with the computer via graphical user interfaces (GUI's). This works fine for most day to day task, but there are many important capabilities that GUI applications cannot provide, and there are many tasks that the shell is much better suited at handling.

If you're accustomed to only using GUI applications, which most people coming from Microsoft Windows or MacOS often are, I highly recommend that you study the Unix shell and command line utilities, you will be positively surprised at how much more efficiently you can handle many tasks using only the shell.

The first Unix shell was the Thompson shell (sh), written by Ken Thompson at Bell Labs and distributed with Versions 1 through 6 of Unix, from 1971 to 1975. The Thompson shell introduced many of the basic features common to all later Unix shells, including piping, simple control structures using if and goto, and filename wildcarding.

The Thompson shell was modeled after the Multics shell, developed in 1965 by American software engineer Glenda Schroeder, who is noted for implementing the first command-line user interface shell while working as a member of the staff at the MIT Computation Center. The Multics shell was itself modeled after the RUNCOM. The rc suffix on some Unix configuration files, e.g. .vimrc, is a remnant of the RUNCOM ancestry of Unix shells. The term stands for the phrase "run commands". rc may also be expanded as "run control", because an rc file controls how a program runs. In The Art of Unix Programming, Eric S. Raymond consistently refers to rc files as "run-control" files.

Tom Van Vleck, a Multics engineer, has also reminisced about the extension rc:

The idea of having the command processing shell be an ordinary slave program came from the Multics design, and a predecessor program on CTSS by Louis Pouzin called RUNCOM, the source of the .rc suffix on some Unix configuration files.

This is also the origin of the name of the Plan 9 shell by Tom Duff, "The rc shell". It is called "rc" because the main job of a shell is to "run commands".

The most widely distributed and influential of the early Unix shells were the Bourne shell and the C shell. Both shells have been used as the coding base and model for many derivative and work-alike shells with extended feature sets.

This is a short list of some of the more popular shells.

Bourne shell

The Bourne shell was the default shell for Version 7 Unix. UNIX-like systems continue to have /bin/sh - which will be the Bourne shell, or a symbolic link or hard link to a compatible shell - even when other shells are used by most users.

The Bourne shell was developed by Stephen Bourne at Bell Labs and it was a replacement for the Thompson shell, whose executable file had the same name - sh. The Bourne shell was released in 1979 in the Version 7 Unix release distributed to colleges and universities. Although it is used as an interactive command interpreter, it was also intended as a scripting language and contains most of the features that are commonly considered to produce structured programs.

It gained popularity with the publication of The Unix Programming Environment by Brian Kernighan and Rob Pike - the first commercially published book that presented the shell as a programming language in a tutorial form.

Features of the Version 7 UNIX Bourne shell include:

The Bourne shell was the first to feature the convention of using file descriptor 2> for error messages, allowing much greater programmatic control during scripting by keeping error messages separate from data.

Stephen Bourne's coding style was influenced by his experience with the ALGOL 68C compiler that he had been working on at Cambridge University. In addition to the style in which the program was written, Bourne reused portions of ALGOL 68's if ~ then ~ elif ~ then ~ else ~ fi, case ~ in ~ esac and for/while ~ do ~ od (using done instead of od) clauses in the common Unix Bourne shell syntax. Although the v7 shell is written in C Bourne took advantage of some macros to give the C source code an ALGOL 68 flavor. These macros (along with the finger command distributed in Unix version 4.2BSD) inspired the International Obfuscated C Code Contest (IOCCC).

C shell

The C shell (csh) is a Unix shell created by Bill Joy, the founder of Sun Microsystems, while he was a graduate student at University of California, Berkeley in the late 1970s. The C shell has been widely distributed, beginning with the 2BSD release of the Berkeley Software Distribution (BSD) which Joy first distributed in 1978. Other early contributors to the ideas or the code were Michael Ubell, Eric Allman, Mike O'Brien and Jim Kulp.

The main design objectives for the C shell were that it should look more like the C programming language and that it should be better for interactive use. And the C shell's built-in expression grammar and support for arrays were all strongly influenced by C.

Like all Unix shells, the C shell supports filename wildcarding, piping, here documents, command substitution, variables and control structures for condition-testing and iteration. What differentiated the C shell from others, especially in the 1980s, were its interactive features and overall style. Its new features made it easier and faster to use. The overall style of the language looked more like C and was seen as more readable.

This following example illustrates the C shell's more C like conventional expression operators and syntax compared to the Bourne shell.

Bourne shell:

if [ $days -gt 365 ]
  echo "This is over a year"

C shell:

if ( $days > 365 ) then
  echo "This is over a year."


tcsh is a Unix shell based on and backward compatible with the C shell (csh). It is essentially the C shell with programmable command-line completion, command-line editing, and a few other features. Unlike the other common shells, functions cannot be defined in a tcsh script and the user must use aliases instead (as in csh). It is the default shell for FreeBSD.


The Korn shell (ksh), written by David Korn and based on the original Bourne Shell source code, was a middle road between the Bourne shell and the C shell.

The Korn shells syntax was chiefly drawn from the Bourne shell, while its job control features mostly resembled those of the C shell. The functionality of the original Korn Shell (known as ksh88 from the year of its introduction) was used as a basis for the POSIX shell standard. A newer version, ksh93, has been open source since 2000 and is used on some Linux distributions.

The Portable Operating System Interface (POSIX) is a family of standards specified by the IEEE Computer Society for maintaining compatibility between operating systems. POSIX defines the application programming interface (API), along with command line shells and utility interfaces, for software compatibility with variants of Unix and other operating systems.

There are several other varians related to the original KornShell, such as:


Bash is a Unix shell and command language written by Brian Fox for the GNU Project as a free software replacement for the Bourne shell. First released in 1989, it has been used as the default login shell for most Linux distributions and all releases of Apple's macOS prior to macOS Catalina. A version is also available for Windows 10 via the Windows Subsystem for Linux. It is also the default user shell in Solaris 11.

The name Bash is an acronym for "Bourne Again Shell", a pun on the name of the Bourne shell that it replaces and the notion of being "born again".

A security hole in Bash dating from version 1.03 (August 1989), dubbed Shellshock, was discovered in 2014 and led to a range of attacks across the Internet. Patches to fix the bugs were made available soon after the bugs were identified. Because of the potential to compromise millions of unpatched systems, Shellshock was compared to the Heartbleed bug in its severity.

Bash is the default interactive command-line shell on most Linux distributions. It is feature rich, actively maintained and generally considered very stable.


Zsh is an extended Bourne shell with many features, including features from Bash, ksh, and tcsh. Paul Falstad wrote the first version of Zsh in 1990 while a student at Princeton University.

Zsh includes features such as:


The Almquist shell (ash) is a lightweight Unix shell originally written by Kenneth Almquist in the late 1980s. Initially a clone of the System V.4 variant of the Bourne shell, it replaced the original Bourne shell in the BSD versions of Unix released in the early 1990s.


In 1997 Herbert Xu ported ash from NetBSD to Debian. In September 2002, with release 0.4.1, this port was renamed to DASH (Debian Almquist shell). Xu's main priorities are POSIX conformance and slim implementation.

Like its predecessor, DASH implements support for neither Internationalization and localization nor multi-byte character encoding (both required in POSIX). Line editing and history support based on GNU Readline is optional.

Because of its slimness, Ubuntu decided to adopt DASH as the default /bin/sh implementation in 2006. The reason for using DASH is faster shell script execution, especially during boot up of the operating system, compared to previous versions of Debian and Ubuntu that used Bash for this purpose, although Bash is still the default login shell for interactive use. DASH became the default /bin/sh in Ubuntu starting with the 6.10 release in October 2006. DASH replaced ash and became the default /bin/sh in Debian 6 (Squeeze).

A result of the shift is that many shell scripts were found making use of bash-specific functionalities, referred to as "bashisms", without properly declaring it in the shebang line. The problem was first spotted in Ubuntu and the Ubuntu maintainers decided to make all the scripts comply with the POSIX standard. The changes were later upstreamed to Debian, which soon adopted DASH as its default /bin/sh too. As a result, all /bin/sh scripts in Debian and Ubuntu are guaranteed to be POSIX-compliant, save for the extensions merged into DASH for convenience. A similar transition has happened in Slackware Linux, although their version of ash is only partially based on DASH.

DASH is also very popular in embedded Linux systems. DASH version 0.3.8-5 was incorporated into BusyBox, the catch-all executable often employed in this area, and is used in distributions like DSLinux, Alpine Linux, Tiny Core Linux and Linux-based router firmware such as OpenWrt, Tomato and DD-WRT.


fish is a Unix shell that attempts to be more interactive and "user-friendly" than those with a longer history. The design goal of fish is to give the user a rich set of powerful features in a way that is easy to discover, remember, and use. fish has its own syntax that is derived neither from the Bourne shell (ksh, Bash, zsh) nor the C shell (csh, tcsh). Also unlike previous shells, which disable certain features by default to save system resources, fish enables all features by default.

Fish has "search as you type" automatic suggestions based on history and current directory. This is essentially like Bash's Ctrl+r history search, but because it is always on instead of being a separate mode, the user gets continuous feedback while writing the command line, and can select suggestions with the arrow keys, or as in Bash, press Tab for a tab completion instead. Tab-completion is feature-rich, expanding file paths (with wildcards and brace expansion), variables, and many command specific completions. Command-specific completions, including options with descriptions, can to some extent be generated from the commands man pages.

Fish has few syntactic rules, preferring features as commands rather than syntax. This makes features discoverable in terms of commands with options and help texts. Functions can also carry a human readable description. A special help command gives access to all the fish documentation in the user's web browser.

What shell should I use?

Unless you have a need for a specific shell, then I recommend you use the default one on the operating system of your choice as it has normally been well integrated into the system.

If you have begun to use shell scripting and you share your scripts with others, e.g. on GitHub or Codeberg, I recommend that you develop your scripts according to the POSIX standard rather than something specific like Bash. Using POSIX will help ensure that your scripts can run on most systems. But if you only write scripts for yourself, then it doesn't matter. You can use the tool ShellCheck (a shell script static analysis tool) to find bugs or "bashisms" in your scripts.

It is also worth keeping in mind that if you are writing large scripts, or use scripts that use complex control flow logic, then you're much better of rewriting such scripts in a real programming language.

I don't recommend you get into the habit of using command auto completion. Command auto completion is a feature that when you type a command and press the TAB key, you will get a list of available options for that specific command. Auto completion for filenames and directories is fine, but auto completion for command options quickly becomes a bad habit. It's much better to get into the habit of reading the man page for the relevant command and typing it out manually. Not only will it help you memorize the command options better, but sometimes what the command option does isn't obvious and you might end up doing something wrong. Also the documentation might contain important information which you tend to skip if you just use command auto completion without reading the man page.

I recommend that you choose the shell that makes you the most productive.

My personal preference is:

Last, but not least, it is worth mentioning that most shells has a Vi mode and an Emacs mode?

Further reading