DEV Community

Cover image for Overhaul your Terminal with Zsh + AutoComplete + More
TimJ
TimJ

Posted on • Edited on • Originally published at timjames.dev

Overhaul your Terminal with Zsh + AutoComplete + More

This guide will look at various ways you can improve your productivity by extending the functionality of your terminal, including:

  • zsh: A powerful shell that extends the feature set of bash.
  • zsh plugins: Auto-suggestions, completion, syntax highlighting and more.
  • prompts + themes: Customize a clean prompt that displays contextual information, either using Powerlevel10k or Posh.

We'll go from this:

bash

To this:

zsh

Getting Started

  1. Install oh-my-zsh for any Unix based shell or WSL2, which bundles zsh with a set of plugins and themes.
  2. Download a Nerd Font and set your favourite terminal to use it. I like Cascaydia Cove Nerd Font the best.

Zsh Plugins

To enable plugins locate your .zshrc in your $HOME directory, and add to the list of plugins:

plugins=(
  git
  ...
)
Enter fullscreen mode Exit fullscreen mode

Plugins Included with oh-my-zsh

  • sudo: Easily prefix your current or previous commands with sudo by pressing esc twice.
  • dotenv: Automatically load your project ENV variables from .env file when you cd into project root directory. By default, it will prompt before loading, but you can turn this off by adding the following to your .zshrc (though be wary of the security implications of this):
export ZSH_DOTENV_PROMPT=false
Enter fullscreen mode Exit fullscreen mode
  • copypath: Copies the path of given directory or file to the system clipboard.
  • copyfile: Puts the contents of a file in your system clipboard so you can paste it anywhere.
  • copybuffer: This plugin binds the ctrl-o keyboard shortcut to a command that copies the text that is currently typed in the command line ($BUFFER) to the system clipboard.
  • command-not-found: provide suggested packages to be installed if a command cannot be found.
  • web-search: This plugin adds aliases for searching with Google, Wiki, Bing, YouTube and other popular services.
  • history: Provides a couple of convenient aliases for using the history command to examine your command line history.
  • dirhistory: Adds keyboard shortcuts for navigating directory history and hierarchy. Uses alt-arrowkeys by default, so ensure these do not conflict with other shortcuts.
  • colorize: Syntax-highlight file contents of over 300 supported languages and other text formats.
  • colored-man-pages: Adds colors to man pages.
  • magic-enter: This plugin makes your enter key magical, by binding commonly used commands to it. You customize the command it uses, and run specific commands in a Git repo:
MAGIC_ENTER_GIT_COMMAND='git status -sb .'
MAGIC_ENTER_OTHER_COMMAND='ls -la .'
Enter fullscreen mode Exit fullscreen mode
  • jsontools: Handy command line tools for dealing with json data.

Depending on what other software you use, there are plenty of lightweight plugins that improve autocompletion and provide aliases among other things. I use:

  • git: Aliases for Git
  • gh: Completions for GitHub cli
  • git-auto-fetch: Periodically run git fetch
  • nvm: Completions for nvm
  • npm: Completions + aliases for npm
  • aws: Completions for aws
  • docker: Completions for docker
  • docker-compose: Completions + aliases for docker compose
  • kubectl" Completions + aliases for kubectl
  • vscode: Aliases for VS Code or VSCodium editor
  • python: Aliases for python
  • pip: Automcompletions for pip
  • tmux: Aliases for tmux

Powerful Plugins

These plugins do not come with oh-my-zsh, so you must clone the repos and place them in ~/ohmyzsh/custom/plugins/ before adding them to the plugins list in the .zshrc.

  • zsh-autosuggestions: Suggests commands as you type based on history and completions, which can then be selected with . zsh-autosuggestions
    • Autosuggestions can either use your history, or tab completion. Set this with the ZSH_AUTOSUGGEST_STRATEGY variable.
    • Has some compatability issues where the suggestion is not cleared after certain actions. To fix this, add the following to your .zshrc:
ZSH_AUTOSUGGEST_CLEAR_WIDGETS+=(bracketed-paste up-line-or-search down-line-or-search expand-or-complete accept-line push-line-or-edit)
Enter fullscreen mode Exit fullscreen mode
  • zsh-syntax-highlighting: Syntax highlighting for the shell zsh. zsh-syntax-highlighting
  • zsh-autocomplete: Provides completion suggestions below the prompt, in addition to a history menu. This one is powerful, but might take some getting used to. Like with autosuggestions, you can choose whether you want to use normal completions (directories, man, etc.) or history search. I like to have autocomplete for normal completions and autosuggestions for history. zsh-autocomplete  If you're like me and don't like the history menu, but want all the other features, you can change the keybinds to use a simple history search in your .zshrc (make sure this is after the plugins have been loaded):
bindkey '\e[A' history-beginning-search-backward
bindkey '\eOA' history-beginning-search-backward
bindkey '\e[B' history-beginning-search-forward
bindkey '\eOB' history-beginning-search-forward
zle -A {.,}history-incremental-search-forward
zle -A {.,}history-incremental-search-backward
Enter fullscreen mode Exit fullscreen mode

 Similarly, to use the default tab completion, set the following options:

zstyle ':autocomplete:*' widget-style menu-select
bindkey -M menuselect '\r' accept-line
Enter fullscreen mode Exit fullscreen mode

 I also don't like the completions to move the prompt around too much, especially for a multiline prompt. We can change this with:

zstyle ':autocomplete:*' list-lines 7
Enter fullscreen mode Exit fullscreen mode

 The plugin also has some issues with the prompt "" showing on some completions and eating inputs. Add this to your .zshrc as a workaround (however this sometimes drops completions entirely, but I still prefer this over loosing inputs):

zstyle ':completion:*' menu select=long
Enter fullscreen mode Exit fullscreen mode

 For a full list of config options, go here.

  • zsh-z: Tool to jump quickly to directories that you have visited frequently.
  • zsh-direnv: Alternative to dotenv, which also provides the use of a .envrc with utility functions.

To take things further, I recommend checking out this curated list of plugins.

Themes + Custom Prompts

We can improve our prompt to contain additional information, such as execution time, performance metrics, and even things like your current Git branch. Set your theme by adding the following to your .zshrc (set to random until you find something you like):

ZSH_THEME="mytheme"
Enter fullscreen mode Exit fullscreen mode

I like agnoster best:
agnoster
As nice as our prompt looks, we can take things further.
We have 2 options:

Option A: Powerlevel10k

Powerlevel10k is a highly customizable theme for zsh. It includes some nice features such as an instant prompt while plugins are loading, and a configuration wizard to get you started.

This is what my prompt looks like:

powerlevel10k

I've modified the configuration a bit to use custom icons for specific directories and cleaned up the git status a bit. See my .p10k.zsh

Option B: oh-my-posh

oh-my-posh:
clean-detailed provides a wide range of themes to choose from, though is missing some features of Powerlevel10k such as instant prompt.

  • Follow installation instructions and find a theme you like. Some favourites of mine are clean-detailed, blueish, or nu4a.
  • Add the path to your chosen theme to .zshrc:
eval "$(oh-my-posh --init --shell zsh --config ~/.mytheme.omp.json)"
Enter fullscreen mode Exit fullscreen mode

Other Customization for .zshrc

For reference, see my complete .zshrc

  • Disable auto zsh updates: zstyle ':omz:update' mode disabled
  • Print ... while waiting for completions to load (doesn't work with zsh-autocomplete): COMPLETION_WAITING_DOTS="true"
  • Custom aliases. For oh-my-zsh, it is recommended to put aliases in a different file: ~/.oh-my-zsh/custom/aliases.zsh. Some I like to use for networking things:
alias get-ports="netstat -tulnp | grep LISTEN"
alias get-router="ip route | grep default"
alias get-ip="hostname -I"
Enter fullscreen mode Exit fullscreen mode

 You can also create an alias function with parameters. For example, to backup a file:

bak() {
  cp $1{,.bak}
}
Enter fullscreen mode Exit fullscreen mode

 We can check that a command exists before setting the alias. For example, we can check docker is installed:

if [ -x "$(command -v docker)" ]; then
    alias dw="watch \"docker ps --format \\\"table {{.Names}}\t{{.Status}}\\\" -a\""
fi
Enter fullscreen mode Exit fullscreen mode

 See all my aliases in my aliases.zsh. Note that for git aliases, it is best to define them in your .gitconfig.

  • Custom keybinds. For example: bindkey '^H' backward-kill-word binds ctrl-bksp to delete by word. Find keycodes here. Those familiar with vim shortcuts can add bindkey -v to their .zshrc. Be wary of conflicts with other keybinds/plugins!
  • Change the default colors for certain directories by adding the following to my .zshrc (go here for color codes):
zstyle ':completion:*:default' list-colors \
  "ow=30;43"
Enter fullscreen mode Exit fullscreen mode

 Alternatively, you can export a complete color scheme from file:

eval "$(dircolors ~/.dircolors)";
Enter fullscreen mode Exit fullscreen mode
  • Set preferred editor for specific files:
alias -s {cs,ts,html,json,xml,md}=code
Enter fullscreen mode Exit fullscreen mode
  • Set preferred editior for ssh, for example:
if [[ -n $SSH_CONNECTION ]]; then
  export EDITOR='vim'
else
  export EDITOR='code'
fi
Enter fullscreen mode Exit fullscreen mode
  • Organize all your environment variables in another file: export $(cat ~/.my_env)
  • You can automatically install packages, for example you can install nvm:
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion
Enter fullscreen mode Exit fullscreen mode

Next Steps

Top comments (0)