Resources for Adapting to zsh in Catalina
macOS 10.15 Catalina brought many big changes to the Mac, like lack of support for legacy 32-bit apps, but one that you could easily have missed is the default Terminal shell switching from bash (the Bourne-again shell) to zsh (Z shell). It’s an easy change to miss if you don’t use the Terminal, but also because if you upgraded from an older version of macOS, bash remains the default (though you’re prompted to switch).
If you’re a Terminal user, you need to be aware of the change, and if you’re merely Terminal-curious, now is a great time to dive in and learn more about the shell, since so many Mac-friendly user guides are being published. In our last reader survey, Terminal coverage wasn’t high on the list of desired topics (“TidBITS 2019 Reader Survey Results,” 6 September 2019), so I won’t dedicate a ton of space to zsh here but will instead point you to resources to help learn more about it.
What is a “shell?”
In the simplest terms, the shell is the command-line environment you use to interact with the operating system. Apple intends users to interact with macOS primarily through its graphical interface, but because macOS is built on top of Unix, it also offers a robust command-line environment.
Don’t confuse a shell like zsh with the Terminal app itself. Terminal loads zsh or another shell of your choice and acts as your graphical interface to the shell, which in turn is the text-based interface to macOS’s Unix foundation.
From the command line, you can execute Unix commands like
ls. A shell used in this way is referred to as an “interactive shell.” You can also string shell commands together with flow control and the like to write shell scripts that automate actions. Those can in turn also be integrated into other automation tools like AppleScript and Keyboard Maestro. In such scripts, you call the shell, usually
sh, with a starting line like
#!/bin/sh. When you use a shell like this, it’s called a non-interactive shell.
What is bash, and why did Apple switch to zsh?
Over the years, programmers have developed numerous shells with different features. Since Mac OS X 10.3 Panther, the Mac’s default shell has been the Bourne-again shell, or bash. It’s also often the default on many Linux distributions, making it something of a de facto standard. Its name is a play on the nigh-ubiquitous Bourne shell (and its many clones, like ash), often referred to by its command,
sh. The Bourne shell dates back to 1976, and while it isn’t generally used interactively, it’s still the basis for most Unix shell scripts because of its ubiquitousness. In 1989, bash emerged from the GNU Project as a newer, more modern version of sh.
There’s nothing wrong with bash, but after version 3.2, released in 2007, the GNU Project relicensed it under the GNU Public License 3.0, which places restrictions on companies like Apple, such as refraining from patent lawsuits and letting people tinker with their computers. Long story short, the 3.2.57 version of bash that ships with macOS is long out of date because Apple refuses to accept GNU’s terms. However, GNU has released small updates over the years to address things like the Shellshock vulnerability—see “Apple Updates Bash for the Shellshock Vulnerability” (29 September 2014).
In contrast, zsh is licensed under a variant of the less-restrictive MIT license. It also offers some advanced features that bash doesn’t.
What does zsh do that bash doesn’t?
The How-To Geek has a brief overview of zsh’s advantages, like automatic
cd, where you can simply type a directory name to navigate to it, and built-in spell-check. zsh also supports plug-ins, which enables things like the popular Oh My Zsh, which adds even more features and makes advanced configuration easier. I also recommend perusing the zsh FAQ, which answers various and sundry questions.
One of my favorite features of zsh is menu autocomplete. In most shells, you can start to type a command or directory name, like
/usr/bi, and then press Tab to autocomplete. In most shells, if there’s more than one autocomplete option, the shell will list the options, but you have to keep typing out the correct path by hand until there’s only one option left, after which you can press Tab to fill it in. With zsh, you can instead configure it to show your options as a menu that you can navigate and select with arrow keys, or with a bit more configuration, vi keybindings or any keys you want. In the screenshot below, I entered
/usr/local/ and hit Tab to see a menu of subfolders.
How do I know which shell I’m using?
Open Terminal and enter one of these commands:
echo $0— which shows the name of the shell.
echo $SHELL— which shows the path to the shell.
The latter command can be especially helpful if you use something like Homebrew to install different shell versions, which exist alongside those Apple ships, just in a different directory (more on that later).
Where can I learn more about zsh?
One of the best free resources for zsh in macOS is Armin Briegel’s Moving to zsh eight-part blog series. Briegel has also released a $9.99 ebook called—you guessed it—Moving to zsh—in Apple’s Book Store. If you’re serious about learning zsh in Catalina, I think it’s a good investment, as it covers in detail everything from explaining what a shell is, transitioning to zsh, and configuring zsh. It will take you from beginner to advanced user quickly, but it isn’t an exhaustive reference. For that, check out the official zsh manual.
The zsh team also offers an official user-friendly guide to zsh, which isn’t as user-friendly or Mac-focused as Briegel’s but has more raw information.
How do I customize zsh?
Out of the box, zsh is a bit spartan. I recommend Briegel’s Moving to zsh, part 2: Configuration Files for a thorough explanation of zsh’s configuration files, though you’ll have to read the rest of the series for configuration tips.
Hold off on installing a plug-in system like the aforementioned Oh My Zsh until you have a good grasp on how zsh works and what you need from Oh My Zsh. No need to make things overly complicated from the start.
Can you share your zsh configuration?
I just copy Luke Smith’s zshrc file into
~/.zshrc. He has set up some nice colors and menu autocomplete with vi keybindings. Here’s a video explaining his configuration in detail.
If you don’t like the vi keybindings and want to use the arrow keys to navigate the menu, simply remove or comment out the five lines under
# Use vim keys in tab complete menu:.
Will my old shell scripts break?
If you started your shell scripts with the standard
#!/bin/sh, you shouldn’t have problems. Catalina still ships with bash, which emulates sh. However, I wouldn’t be surprised if Apple were to remove bash entirely in the future. Apple suggests having zsh emulate sh by adding the
--emulate sh option to zsh, so you can start a script with
#!/bin/zsh --emulate sh. (Note that this won’t work with the version of zsh that ships with Mojave.) I also refer you to Briegel’s Moving to zsh, part 8, which covers scripting with zsh.
My default shell is still bash. How do I switch to zsh?
Although zsh was not the default in older versions of macOS, nor is it the default in Catalina for older accounts which were created with bash as their default shell, Apple has long included zsh with macOS. You can give it a whirl right now by typing
zsh at the command line. Type
exit to leave zsh. If you want to set it as your default shell, Apple offers a couple of ways to do so, as well as a way to change what Terminal uses without changing the default for your account.
I don’t like zsh. Can I go back to bash? Preferably a newer version?
Yes, and it’s easy to do so. Just follow the link to Apple’s how-to page above and replace
/bin/zsh in the instructions with
However, you may not want to remain on Apple’s ancient version of bash. That’s where Homebrew comes in handy. Once you install it, running
brew install bash will update the latest version from Homebrew, which will be installed in
/usr/local/bin/bash. Note that you’ll have Apple’s version in
/bin/bash and Homebrew’s version in
/usr/local/bin/bash. If you need a feature from the newer version of bash that Homebrew installs, be sure to start your scripts with
If you don’t or can’t use Homebrew, Briegel has instructions on how to build and install bash manually.
Are there alternatives to bash and zsh?
There are an absurd number of shells out there, but bash and zsh are the most common and the most worth your time to learn. However, Brett Terpstra has been documenting his experiments with the fish shell:
Fish features advanced autosuggestion and expansions, does cool syntax highlighting, offers a “sane” scripting toolset, has an array of existing plugins and themes, and even sports a browser-based configuration tool that’s pretty awesome.
I haven’t tried it, but it may be your cup of tea, er, barrel of fish.
One additional very important (IMO) resource if you are thinking about switching to zsh is The Zsh Mailing List aka “zsh-users”.
I have been a member of that email list since at least 1995 and have found it to be invaluable, and the people are extremely helpful and friendly, unlike some corners of the Internet. It’s a small group, but if you need help with a zsh-specific question, it’s probably the best place to turn.
Thanks. This was a super-helpful article. I know not a ton of people were interested in Terminal in the survey, but it interests me a ton. I’m a programmer and I spend a fair amount of time in the terminal. I was aware that macOS’ bash and some other command-line tools are archaic because of the GPL license. I’m not switching to Catalina any time soon, but now I’m excited to switch to zsh. This article gave me pointers to what look to be great tools to give me a good start.
Like Steve, I also spend a lot of time in shells so I definitely appreciate articles like these. Thank you, Josh and TidBITS team.
I would disagree with this, install oh_my_Zsh right away because that gives you an idea of just how powerful zsh is. The configuration is very simple for anyone who is familiar with using a shell.
Thanks, Steve and Simon, I’m glad you guys enjoyed the article. I’d love to write more about the command line, and I will whenever I get an excuse
OH, and here is the most useful zsh function I have found, it turns ^Z into a toggle. It’s like magic.
Editting in vim, hit ^Z to get to the shall, do some stuff, hit ^Z and you’re right back in vim!
Join the discussion in the TidBITS Discourse forum