Home The Ultimate Terminal Setup for macOS: Tips, Tricks, and Customizations
Post
Cancel

The Ultimate Terminal Setup for macOS: Tips, Tricks, and Customizations

Intro

The terminal, also known as the command line interface (CLI), is a powerful tool that can greatly enhance our experience on macOS. One of the main advantages of using the terminal is that it gives us access to a wide range of powerful command-line tools and utilities. Additionally, we can increase our efficiency and speed of navigation and management of files and directories. The terminal also allows for scripting and automation of tasks through the use of shell scripts and gives us access to advanced features and settings that may not be available through the graphical user interface (GUI). By mastering the terminal, we can greatly increase our productivity and efficiency as power users.

In this article, I will guide you through customizing and optimizing your terminal experience on macOS. The goal is that by the end you should have an advanced terminal configuration at your disposal.

iTerm2 end result

I am not affiliated with any of the apps or programs that I may mention or recommend. Any views or opinions expressed are solely my own and do not represent the views or opinions of any other organization or entity.

Steps

  1. Homebrew
  2. iTerm2
  3. Oh My Zsh
  4. rbenv and pyenv
  5. powerline-shell
  6. Enable Touch ID for sudo
  7. 1Password CLI

Homebrew

Make sure you have Homebrew installed. We will use it to install tools and applications.

iTerm2

First, let’s install iTerm2.

1
brew install --cask iterm2

Configuring the basic behaviours of iTerm2 is pretty straightforward as it already has great presets. If you want to customize it further I recommend starting with the official documentation. Usually, I only configure the following:

Changing the colours

Colours are always a question of personal preference. My favourite one so far is the Solarized Dark as it’s easy on my eyes. If you don’t like dark colours consider using Solarized Light. Experiment with the other presets as well.

Go to Settings (Cmd + ,) -> Profiles -> Default -> Colors -> Color Presets... -> Solarized Dark

You can find a lot more in the Online Gallery.

Unlimited scrollback

Today’s Macs have so much RAM available we can safely increase or even completely remove the cap on history (scrollback). If you are a developer and compile or release something, the output can be extremely verbose. To be able to see everything properly it can be a good idea to turn off the limit on the scrollback buffer. If you experience a performance hit then you should fine-tune the Scrollback lines settings instead.

Go to Settings -> Profiles -> Default -> Terminal -> Unlimited scrollback

Natural Text Editing

The last setting is for convenience. If you want to edit a command before executing and would like to use the same shortcuts you know and love everywhere in macOS, like jumping left and right by word (Option + Left / Option + Right) or going to the beginning (Cmd + Left) or the end of the line (Cmd + Right), you should set the Key Mapping to Natural Text Editing.

Go to Settings -> Profiles -> Default -> Keys -> Key Mappings -> Presets... -> Natural Text Editing

I think it’s easier than defining escape sequences to all our shortcuts.

Oh My Zsh

What is Oh My Zsh and why do want it?

Oh My Zsh is an open source, community-driven framework for managing your zsh configuration.

Alright, but what is zsh?

ZSH, also called the Z shell, is an extended version of the Bourne Shell (sh), with plenty of new features, and support for plugins and themes. Source

Makes sense, except what is a shell?

A shell is a software program used to interpret commands that are input via a command-line interface, enabling users to interact with a computer by giving it instructions. Source

Apple has already replaced the default shell from bash to zsh in macOS Catalina. In my eyes, we are just improving it further with Oh My Zsh which comes with tons of features. Let’s install it!

1
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

After the successful installation, we can start customizing it by editing our ~/.zshrc file. The contents of this file are executed every time we create a new session.

This is my main config. (Will be extended in the upcoming steps.)

1
2
3
4
5
6
7
8
9
ZSH_THEME="robbyrussell"

zstyle ':omz:update' mode auto
zstyle ':omz:update' frequency 1

plugins=(bundler git macos xcode)

export LANG=en_US.UTF-8
export EDITOR='vim'

First, we can set up our theme. If you don’t like this one, there is a lot more to choose from.

The next two lines just make sure that our Oh My Zsh is automatically updated every day.

Following that we can customize the plugins we use. There is a myriad of available plugins, but in my experience, a large portion of them just adds aliases that are pretty hard to remember when I can simply memorize the actual command itself. No need for indirections. For example, the brew plugin creates an alias bubc for brew upgrade && brew cleanup. Which one seems easier to remember? For me, it’s usually the latter. Don’t get me wrong, these aliases can be useful, using the bundler plugin saved me a lot of time. Instead of writing manually bundle install 50+ times a day, I just say bi and we are ready to go. Experiment with what works for you.

What’s an alias? The alias command lets us create shortcuts for commands that we may need to enter frequently, making them easier to remember and use.

The last two lines set up the language environment and the preferred editor. If you are not familiar with the basics of vim I suggest choosing something else, like nano.

rbenv and pyenv

As a developer or even a power user, sooner or later you’ll have to use Python and/or Ruby. If you are like me, working on multiple projects that use different versions of Python and Ruby you have to figure out how to handle multiple versions at the same time. I found rbenv and pyenv reliable and easy to use with similar commands. Both can be installed with Homebrew.

1
2
brew install rbenv ruby-build
brew install pyenv

At the end of the installation brew will tell us about the initialization of these environments. The point is that when we start our terminal session we have to initialize the Ruby and Python environments. We can do this by putting the following commands into our ~/.zsrc.

1
2
3
4
5
6
7
8
9
# Ruby
if command -v rbenv 1>/dev/null 2>&1; then
  eval "$(rbenv init -)"
fi

# Python
if command -v pyenv 1>/dev/null 2>&1; then
  eval "$(pyenv init -)"
fi

After we’ve edited our ~/.zshrc we have to reload the configuration by either closing the terminal and opening a new session, or executing the following command.

1
source ~/.zshrc

Finally, we can install our Ruby and Python.

1
2
3
4
5
6
7
8
# List the latest stable versions and choose one (at the time of writing it's 3.2.0)
rbenv install -l

# Install Ruby 3.2.0
rbenv install 3.2.0

# Make Ruby 3.2.0 the default Ruby on the computer (first in PATH)
rbenv global 3.2.0
1
2
3
4
5
6
7
8
# List the latest stable versions and choose one (at the time of writing it's 3.11.1)
pyenv install -l

# Install Python 3.11.1
pyenv install 3.11.1

# Make Python 3.11.1 the default Python on the computer (first in PATH)
pyenv global 3.2.0

powerline-shell

The Open Source powerline-shell can make our terminal look even better. Installation is pretty easy after we have a Python installed.

1
pip install powerline-shell

After the successful installation let’s create the config file for it and place it here: ~/.config/powerline-shell/config.json. The configuration is further explained here. Customize for your needs.

1
2
3
{
  "segments": ["virtual_env", "ssh", "cwd", "git", "hg", "jobs", "root"]
}

Finally, we have to edit our ~/.zshrc once again to initialize it in every session.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Powerline
function powerline_precmd() {
    PS1="$(powerline-shell --shell zsh $?)"
}

function install_powerline_precmd() {
  for s in "${precmd_functions[@]}"; do
    if [ "$s" = "powerline_precmd" ]; then
      return
    fi
  done
  precmd_functions+=(powerline_precmd)
}

if [ "$TERM" != "linux" ]; then
    install_powerline_precmd
fi

Once you start a new session (or source the zsh config), you will notice these weird-looking characters. Let’s fix those by installing a proper font.

Meslo Powerline Font

  1. Download the font from here: Meslo Powerline Font.
  2. Open it and install it via macOS’s Font Book.
  3. In iTerm2 change the font: go to Settings -> Profiles -> Default -> Text -> Font and select Meslo LG M for Powerline. Optionally you can also adjust the size of the text. I prefer 14pt.

Enable Touch ID for sudo

Up until now, most of our commands ran without having to type in our password.

The Unix and Linux operating systems’ sudo command stands for superuser do. A user can run a command with the superuser’s (also known as the root user’s) privileges, enabling them to carry out operations that the system would otherwise restrict. You will be prompted for your password when you use sudo to run a command. This is a safety precaution to guarantee that only users with permission to act as superusers can. If you have a Touch ID on your Mac or Magic Keyboard you can set it up to be able to use it instead of typing in the password.

A word of advice: DO NOT MAKE A MISTAKE EDITING THE FOLLOWING FILE!

Open the sudo file:

1
sudo vim /etc/pam.d/sudo

Then insert the following line to the top:

1
auth sufficient pam_tid.so

Save the file and close it. Open a new session (after typing in your password you will be able to sudo for a little while) and test your setting, e.g.: sudo ls. It should prompt you to the system’s Touch ID screen.

Sudoing with Touch ID

1Password CLI

I love 1Password. It really feels like I’m using a first-party application. Recently they’ve come up with something even more amazing: the 1Password CLI. There are tons of possibilities with it, I’m still playing with it but it’s already useful for a bunch of things. Let me show you some.

If you have a 1Password subscription and the app is installed already, you can install the 1Password CLI via brew:

1
brew install --cask 1password/tap/1password-cli

You can also verify if the installation was successful:

1
op --version

To set it up just enable Touch ID and connect the two programs and finally log in with the CLI.

  • Go to Settings -> Security -> turn on Touch ID, then go to Settings -> Developer -> turn on Connect with 1Password CLI. (Later we will also turn on the Use the SSH agent.) Sudoing with Touch ID
  • Sign in to the 1Password CLI by issuing any command, like op vault ls.

A huge problem even for experienced, senior software engineers is how they are storing their passwords and secrets. Sometimes they just put them in an environment variable or a configuration file. This is really bad. With 1Password CLI we can do better without sacrificing convenience. Currently, I’m mainly using it for two things:

  • Store and load secrets securely
  • Authenticate with SSH automatically

Store and load secrets securly

With 1Password CLI, you can use secret references to securely load secrets saved in 1Password in environment variables, configuration files, and anywhere else you might need them, without putting any plaintext secrets in code. At runtime, secret references are automatically replaced with the actual secrets they refer to. Source

Let’s see an example. We are using Danger to automate some parts of our code review process. If we want to connect it to Bitbucket Cloud, we need the UUID, the username and an app password. I stored these in 1Password and then created environment variables in my ~/.zshrc.

1
2
3
export DANGER_BITBUCKETCLOUD_UUID="op://Work/Atlassian/Info/UUID"
export DANGER_BITBUCKETCLOUD_USERNAME="op://Work/Atlassian/Info/username"
export DANGER_BITBUCKETCLOUD_PASSWORD="op://Work/Atlassian/AppPasswords/Danger"

Before executing the danger command locally, I just have to prefix it with op run -- and the environment variables will be replaced with the actual passwords. It’s amazing!

1
op run -- bundle exec danger pr https://bitbucket.org/...`

Note: running this command prompts for your Touch ID.

Authenticate with SSH automatically

I have a lot of SSH keys, usually using a different one for each and every Git provider and client we are working for. Managing these, especially if you have multiple Bitbucket accounts for example can be a pain. Writing complex ssh configurations. 1Password CLI comes to our rescue here as well. First, we can store our SSH keys in 1Password vaults, which is already better than the default ~/.ssh directory. The real kicker, however, is that we can automatically authenticate with our Touch ID when we perform git commands. It’s like magic. 🎉

To set this up follow the guide. The main steps are:

  • Turning on Settings -> Developer -> Use the SSH agent
  • Add the proper config to your SSH config (~/.ssh/config). 1Password settings will show it.
1
2
Host *
	IdentityAgent "~/Library/Group Containers/XXXXXXXXXX.com.1password/t/agent.sock"
  • Add your SSH keys to your Vault
  • Done ✅

Other ideas

By browsing the documentation we can see that there are other possibilities, like

Acknowledgement

Years ago I’ve started my terminal customization journey thanks to Felix Krause, the original creator of fastlane.tools. To this day I still use a large part of his ideas.

Summary

If you’ve reached this point you should have a customized terminal environment setup. Congratulations! As a developer or power user, setting up our terminal can significantly increase our productivity and efficiency. We can improve our command-line experience by streamlining our workflow, adding useful command-line tools, and customizing our prompt. Additionally, we can manage our code changes and collaborate with others by setting up our terminal to work with version control systems like Git. With 1Password we can also mitigate some of the security issues, but don’t forget to keep your command-line and terminal tools up to date.

Versions

  • macOS Ventura 13.1 (22C65)
  • iTerm Build 3.4.19
  • rbenv 1.2.0
    • Ruby 3.2.0
  • pyenv 2.3.10
    • Python 3.11.1
  • 1Password for Mac 8.9.13 (80913040)
    • 1Password CLI 2.12.0
This post is licensed under CC BY 4.0 by the author.