A Better OS X Terminal

With help from Brew, ZSH, Prezto and iTerm

September 17, 2017 · 1541 words · 8 minute read
#macos #tutorial

A lot of my time at work and at home is spent in the terminal. Whether it’s managing systems, developing software or writing articles like this it seems like it’s one of the few applications I always have running.

In this article I’ll take you through the process I use to setup a new Mac and some of reasoning behind my decisions. The intent of this article is not only to be a guide for the reader, but a reference for myself so I’ll keep this updated as things change around.

I’d like to thank my old collegue Brandon for introducing some of this fantastic software to me.


1. iTerm2

While the default ‘Terminal’ application that ships with OS X is functional, it leaves a lot to be desired in my opinion.

There’s an American proverb that says “The best things in life are free” and I find this to be true, especially with software like iTerm2. Here’s a small portion of what it can do:

  • Easily split panes horizontally (⌘ + Shift + D) and vertically (⌘ + D)
  • Send the same command to multiple sessions
  • Bring to foreground with a hotkey or always available window (like Quake console)
  • Instant replay (see what has been previously displayed)
  • Additional features

There may be better terminal software out there for the Mac, but I have yet to find it. Any time I want to do something new with my terminal, I find iTerm2 already has an option for it. I think it’s summed up best by this quote from iTerm2 themselves: “iTerm2 brings the terminal into the modern age with features you never knew you always wanted.”

Installation is simple, just head over to the iTerm2 downloads page and grab the latest stable version.


2. Homebrew (Brew)

If you use a Mac and haven’t heard of Homebrew, it’s time to come out from under that rock you’ve been living under to check out “The missing package manager for macOS”. Homebrew, written in Ruby and is akin to package manager software such as; ‘Yum’, ‘Aptitude’, ‘pkg’ and ‘chocolatey’. Homebrew allows you to install and manage a curated list of software from the terminal with ease.

You can check out a list of available formulas (there are quite a few).

Homebrew installation is straightforward, just be sure your Mac meets the following requirements:

  • An Intel CPU
  • OS X 10.11 or higher
  • A Bourne-compatible shell for installation (e.g. bash or zsh)
  • Ruby (comes shipped with OS X >= 10.11)

Then simply run the following command (do not use sudo) in your shell and follow the prompts:

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

The -e flag is to specify a script and tell Ruby not to search the rest of the arguments for a script file name.

Once complete, you can verify that Homebrew is installed by running:

brew --version

3. Z Shell (Zsh)

This can be a touchy subject, the Bourne Again SHell a.k.a. Bash has been around for many years and is the standard shell for many popular Linux distributions as well as OS X and thus has been used and loved by many (including myself) for a long time.

My interest in Zsh started when a colleague explained a few of its out of the box quality of life features to me such as its intelligent tab-completion. With its improvements and vast customization options, I’ve never found myself wanting to go back to Bash. However, when using Bash I’m always quickly reminded why I switched to Zsh.

A high level overview from the Zsh FAQ:

Zsh is a UNIX command interpreter (shell) which of the standard shells most resembles the Korn shell (ksh); its compatibility with the 1988 Korn shell has been gradually increasing. It includes enhancements of many types, notably in the command-line editor, options for customising its behaviour, filename globbing, features to make C-shell (csh) users feel more at home and extra features drawn from tcsh (another `custom' shell).

A few notable out of the box Z Shell features:

  • Tab-complete commands from history
  • Tab-complete not just based on the beginning of an object name
  • ‘cd’ tab turns into a selectable list of objects you can navigate with the arrow keys
  • Shared command history between all shells
  • Extensive globbing support
  • Countless available plugins and an active plugin community
  • Seamless transition from Bash

The amount of customization options is immense, this list barely scratches the surface. I recommend giving it a try to see what you think, it’s a great shell that quickly grows on you.

To install Zsh using Homebrew, run the following command:

brew install zsh

To install additional zsh-completions that are not yet available in Zsh:

brew install zsh-completions

You can now change your shell using chsh

chsh -s $(which zsh)

4. Prezto

Now that you’ve got Zsh running in iTerm, it’s time to put the finishing touches on your terminal. Over the last 5 plus years of using Zsh I’ve used both Oh My Zsh and Prezto. Prezto started as a fork of Oh My Zsh, but was eventually completely rewritten with optimization in mind. That focus on optimization definitely shows and it’s well worth choosing Prezto of Oh My Zsh for it.

From the Prezto README:

Prezto is a configuration framework for Zsh, it enriches the command line interface environment with sane defaults, aliases, functions, auto completion, and prompt themes.

Installing Prezto is a tiny bit more involved than the previous steps, but isn’t difficult by any measure. The following is lifted from the installation guide in the Prezto repository with a few additional notes. If for whatever reason, something below doesn’t work for you, please defer to the official guide.

Prezto requires a Zsh version greater than 4.3.11. If you’ve followed this guide, you will have a much newer version than that. If you want to check which version of Zsh you have installed, run:

zsh --version

Make sure you’re using Zsh. You can check by running the following command in your shell:

echo $SHELL

It should return something similiar to /usr/local/bin/zsh.

If you’re not using Zsh, you can switch to it by running zsh or restarting iTerm (or creating a new session in iTerm) if you’ve set Zsh as your default shell using chsh -s $(which zsh) from the previous step.

zsh

Install git if it’s not already installed. To check if git is installed, run:

git --version

To install git with Homebrew, run:

brew install git

Clone the Prezto repository in your home directory:

git clone --recursive https://github.com/sorin-ionescu/prezto.git "${ZDOTDIR:-$HOME}/.zprezto"

Create a new Zsh configuration by copying the provided files from the repository you just cloned:

Note: If you already have any of the provided configuration files, ln will cause error. In simple cases you can load prezto by adding the line source "${ZDOTDIR:-$HOME}/.zprezto/init.zsh" to the bottom of your .zshrc and keep the rest of your Zsh configuration intact. For more complicated setups, it is recommended that you back up your original configs and replace them with the provided prezto runcoms.

setopt EXTENDED_GLOB
for rcfile in "${ZDOTDIR:-$HOME}"/.zprezto/runcoms/^README.md(.N); do
  ln -s "$rcfile" "${ZDOTDIR:-$HOME}/.${rcfile:t}"
done

setopt EXTENDED_GLOB tells Zsh to treat the ‘#’, ‘~’ and ‘^’ characters as part of patterns for filename generation.

The for loop goes through the files in the ~/.zprezto/runcoms directory (excluding the README.md) and creates symbolic links for them in your home directory. Zsh/Prezto will load these files in the order defined in the README.md when you start the shell.


5. Customizing Zsh & Prezto

The customization options for Zsh and Prezto are vast and far beyond the scope of this article, however, I’ll provide a kickstart to get you going.

You can customize Prezto in your ~/.zpreztorc config file.

Prezto comes with a bunch of features that are disabled by default, so be sure to check out the comments in your ~/.zpreztorc and configure the settings to your preference.

Modules add additional functionality to Prezto/Zsh, you can check them out in the modules directory found either in the Prezto respository or ~/.zprezto/modules. Read the README in each of the module directories for more information. Here’s a quick list to get you started (this goes in ~/.zprezto):

zstyle ':prezto:load' pmodule \
  'environment' \
  'terminal' \
  'editor' \
  'history' \
  'directory' \
  'spectrum' \
  'utility' \
  'completion' \
  'git' \
  'syntax-highlighting' \
  'history-substring-search' \
  'prompt'

Prezto will look for modules in ~/.zprezto/modules and ~/.zprezto/contrib by default if you want to load external modules you can put them in there, just make sure the name is unique. If you want to keep things organized, you can tell Prezto to look in other directories using the zstyle ':prezto:load' pmodule-dirs $HOME/<directory> setting in ~/.zpreztorc.

Change your editor key mapping by editing the following option, by default it uses emacs but I prefer vi bindings.

zstyle ':prezto:module:editor' key-bindings 'vi'

You can view available prompt themes with prompt -l. If you want to preview a theme you can use prompt -p <theme_name>.

I like the paradox theme, so let’s that in our ~/.zpreztorc file as well:

zstyle ':prezto:module:prompt' theme 'paradox'

Conclusion

That about covers the scope of this article. Hopefully you found it helpful and I hope you enjoy your fancy new terminal experience!

If you have any questions or comments, you can connect with me on matrix at @bryan:matrix.twosuns.net.