Pimp your CLI
Tags: linux, tutorial, beginners, productivity
Published: 2023-12-19 17:20:25

_Also available in [spanish](https://dev.to/josemunoz/enchula-mi-consola-5d70)_

As a developer, the command line is one of the tools you will be using most frequently. It can be intimidating to venture into the world of CLI tooling but I can assure you it is one of the most rewarding experiences too. In this post I want to walk ya'll through my personal CLI setup. It is based on 3 technologies which I'll coin as the "Holy Trinity" of the command line: [TMUX](https://github.com/tmux/tmux/wiki), [ZSH](https://www.zsh.org/), & [Neovim](https://neovim.io/).

## Prerequisites:
- Linux, MacOS, or WSL

- Your favourite [NerdFont](https://www.nerdfonts.com/font-downloads)

- A decent terminal application (i.e: [iterm2](https://iterm2.com/), [alacritty](https://alacritty.org/), etc.)

- you OS’s equivalent of `apt install zsh tmux neovim`,
 I'm using Debian for this demo

## TMUX

The cornerstone of the command line experience in my opinion has to be the terminal multiplexer: tmux. 
In simple terms (pun intended) tmux allows you to split your terminal into different panes, windows, or sessions. Have you ever ssh'd into a server to start a long running process and the screen-saver killed your session? tmux will keep the session running even if the client disconnects and you can pick up where you left by just attaching to the previous session. There is an entire ecosystem with themes, plugins, and utilities built around tmux. Checkout the [tmux cheat sheet](https://tmuxcheatsheet.com/) to get familiar with the basic functionality and keyboard shortcuts. This is really just the tip of the iceberg, I encourage you to dive deeper and customize your setup to your liking. By default your experience might not look like much:

![tmux before](https://i.imgur.com/LLIs0Cb.png)

We will start by creating a custom tmux configuration by running `nvim ~/.tmux.conf`

One of the first life comfort changes I make to my tmux configuration is to set the index to base 1. On your keyboard its easier to switch between the numeric keys in order rather than starting in one end and reaching to the opposite end for the rest of the options.

```sh
# start windows, sessions, and panes with 1
set -g base-index 1
set -g pane-base-index 1
set-window-option -g pane-base-index 1
set-option -g renumber-windows on
```

I also like to change the leader key combination, you're going to be using this key-combo a lot so make sure you set it to something comfortable.

```sh
# change prefix
unbind C-b
set -g prefix C-Space
bind C-Space send-prefix
``` 

Lastly, one of the configs that I personally think should be the default is to open a new pane or window on the Current Wording Directory.

```sh
 # split in cwd
 bind '"' split-window -v -c "#{pane_current_path}"
 bind '%' split-window -h -c "#{pane_current_path}"
```

This will provide you with a solid base to configure further on your own, but in order to _really_ take it to the next level, you have to be able to tap into Tmux's plugin ecosystem. TPM (Tmux Plugin Manager) can be installed by cloning its repository into Tmux's plugins folder.

```sh
git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm
```

after that, you will have to keep this at the very end of the file:

```sh
# Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf)
 run '~/.tmux/plugins/tpm/tpm'
```

And a list of your desired plugins at the top, starting with tpm of course:

```sh
set -g @plugin 'tmux-plugins/tpm'
```

I would also recommend adding `tmux-plugins/tmux-sensible`, and `catppuccin/tmux` for usability and aesthetics. Your `.tmux.conf` should look like this: 

```sh
 # List of plugins
 set -g @plugin 'catppuccin/tmux'
 set -g @plugin 'tmux-plugins/tpm'
 set -g @plugin 'tmux-plugins/tmux-sensible'
 
 # split in cwd
 bind '"' split-window -v -c "#{pane_current_path}"
 bind '%' split-window -h -c "#{pane_current_path}"
 
 # start windows, sessions, and panes with 1
 set -g base-index 1
 set -g pane-base-index 1
 set-window-option -g pane-base-index 1
 set-option -g renumber-windows on
 
 # change prefix
 unbind C-b
 set -g prefix C-Space
 bind C-Space send-prefix
 
 # Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf)
 run '~/.tmux/plugins/tpm/tpm'
```

assuming you're already running tmux, you can run `tmux source-file ~/.tmux.conf` to load the new config. After the new config has been loaded you need to install the plugins by using your new key-combo and `Shift+I`. Depending on your font you might have to adjust the font size, 16 is a good default.

![not too shabby](https://i.imgur.com/fv9TlyP.png)

If any of the plugins fails to install you can always use this same mechanism of cloning the repo and calling "install" after. Make sure to checkout [Tmux's Awesome list](https://github.com/rothgar/awesome-tmux) for more.

## Z Shell

ZShell is an alternative to bash a.k.a. "Bourne-Again SHell". It does everything that bash does and just like Tmux it is extensible via a healthy plugin ecosystem. By this point I hope you have already tried to run `zsh` on your terminal. At first it won't look like much has changed but with the right plugins this can become your best friend on the command line.
The first thing we need to do is to install [oh-my-zsh](https://ohmyz.sh), a framework on top of zsh that manages configs, plugins, themes, and more.

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

Once you complete the installation you should have a new configuration file called `.zshrc` on your home folder, if you open it with `nvim ~/.zshrc`, you will see that it already has been populated with the default `oh-my-zsh` configuration. One of the most essential plugins for me is `zsh-autosuggestion` which provides autocomplete functionality, to install you need to add it to the plugins list on the configuration: 

```sh
plugins=( 
    # other plugins...
    zsh-autosuggestions
)
```

Clone the repo to the `oh-my-zsh` plugins folder like so:

```sh
git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
```

Lastly, you want to source the new config using `source ~/.zshrc`, do this every time you edit the config.


My prefered theme is [powerlevel10k](https://github.com/romkatv/powerlevel10k#oh-my-zsh), yup it’s over nine thousand! 

![over nine thousand!](https://i.imgur.com/MeJrynw.gif) 

P10k is a feature-rich theme which has a lot of eye candy, it is very customizable and even has a wizard to help with the first config. 

![powerlevel10k different styles](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zbowsak7ylkggdb37spo.png)

To install it find the current theme on your config and set it to:

```sh
ZSH_THEME="powerlevel10k/powerlevel10k"
```

and then clone the repo into your `oh-my-zsh` themes folder. Don’t forget to source the new config!

```sh

git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k

```

Make sure to checkout [Zsh's Awesome List](https://github.com/unixorn/awesome-zsh-plugins) for more.

## NeoVIM

NeoVim was released in 2014 as a fork of VIM that adds support for Lua. Just like its predecessor, there is quite the learning curve, but the payoff as a keyboard-first editor is truly rewarding. You have endless options to customize your setup and I encourage you to start by changing individual things to your liking (like tabs vs spaces) and to make a custom configuration of your own. Lua is already popular as a systems language so it was a good replacement for vimscript and it makes it easier to write plugins in comparison which means there is a good selection of plugins available for Neovim. Its easy to get option paralysis with the vast amount of customization and plugins, so there’s popular configurations of neovim that put together a nice UI with modern IDE functionalities and we can start with those like [AstroNvim](https://astronvim.com/) and [NvChad](https://nvchad.com/).

<a href="https://www.youtube.com/watch?v=Mtgo-nP_r8Y">
  <img src="https://i.ytimg.com/vi/Mtgo-nP_r8Y/maxresdefault.jpg" />
</a>

In order to install a custom config you’re going to (you guessed it) clone the repository into the config folder and run `nvim` to load the new config.

```sh
git clone --depth 1 https://github.com/AstroNvim/AstroNvim ~/.config/nvim
```
or
```sh
git clone --depth 1 https://github.com/NvChad/NvChad ~/.config/nvim 
```

If you are switching between configs it is recommended to make a backup of your current config by running the following

```sh
mv ~/.config/nvim ~/.config/nvim.bak
mv ~/.local/share/nvim ~/.local/share/nvim.bak
mv ~/.local/state/nvim ~/.local/state/nvim.bak
mv ~/.cache/nvim ~/.cache/nvim.bak
```

The basic plugins will be downloaded on the first run using [Lazy](https://github.com/folke/lazy.nvim), a package manager for Neovim that loads only the necessary plugins as you use them. Once it's done you should be looking at a full-fledged IDE.

![final setup](https://i.imgur.com/CEHh02Y.png)

Here are some _quality-of-life_ improvements I like to add to my setup in order to have Neovim across the whole system. First I update the global editor settings for git:

```sh
git config —global core.editor nvim
```

A lot of things on the command line default to `vi` as their editor, so I like to alias it to `nvim` to make sure I get a consistent experience

```sh
alias vi=“nvim”
```

Sometimes you want to edit something that requires privileged access and you run `sudo nvim` only to be surprised with the default config. This is because nvim loads config from the user's home folder and that context changes when you run something as root. To fix this you can run `sudo` with option `-E` to include the current environment variables. Add it to your `.zshrc` as a _quality-of-life_ improvement.

```sh
alias sudo=“sudo -E”
```

Make sure to checkout [Neovim's Awesome List](https://github.com/rockerBOO/awesome-neovim) for more.

## Conclusion

Having a nice environment helps when you're spending time on the command-line. It took me a while to figure out that you could do so much with CLI applications. I hope that this becomes the starting point of your command-line journey. Let me know if you have any other utilities I can add to my CLI setup on the comments! 

## Bonus

If you want to take your SSH to the next level I highly recommend you read [Carlos Becker's SSH Tips and Tricks](https://carlosbecker.com/posts/ssh-tips-and-tricks/) blog post.