youtube.nixfred.com nixfred.com

This Zsh config is perhaps my favorite one yet.

Dreams of Autonomy builds a complete zsh environment from an empty .zshrc, line by line, chasing what he calls a zenful terminal: minimal on screen, powerful underneath, and fast enough that opening a new window has no perceptible delay. The build is zinit as a self bootstrapping plugin manager, Powerlevel10k in Pure style with instant and transient prompt, the big three plugins (syntax highlighting, completions, autosuggestions), a properly shared history with prefix matched search on Ctrl+P and Ctrl+N, case insensitive colored completions, fzf plus fzf-tab turning both reverse search and Tab into a fuzzy finding window with directory previews, Oh My Zsh plugins pulled in as individual snippets without installing Oh My Zsh, and zoxide replacing cd outright. Every line is explained rather than pasted, including the parameter expansion in ZINIT_HOME, what zinit's ice command means, and why zinit cdreplay -q has to sit under compinit. The finished config is published as zensh.

Published May 16, 2024 17:23 video 30 min read Added Aug 24, 2026 Open on YouTube →

At a glance

Dreams of Autonomy builds an entire zsh environment from an empty .zshrc, line by line, and the whole thing fits on one screen. The goal he states up front is "zenful": as little on screen as possible, as much interactive power as possible underneath, and a startup so fast that opening a new terminal window has no perceptible delay. The build is zinit as the plugin manager (self bootstrapping, so the config clones its own package manager on first run), Powerlevel10k in Pure style as the prompt, the big three plugins (syntax highlighting, completions, autosuggestions), a properly configured shared history with prefix search on Ctrl+P and Ctrl+N, case insensitive and colored completions, fzf plus fzf-tab to turn both reverse search and tab completion into a fuzzy finding window with directory previews, Oh My Zsh plugins pulled in as individual snippets without installing Oh My Zsh itself, and zoxide taking over cd. Every line is explained rather than pasted, including the parameter expansion trick in ZINIT_HOME, what zinit's ice command actually means, and why zinit cdreplay -q has to sit under compinit. This page rebuilds the whole tutorial in order, with the config assembled as he assembles it and the finished .zshrc reproduced whole at the end. The finished result is published as zensh.

The pitch: calm plus power, with no startup cost (0:00)

If you are like him, you spend a lot of time working inside your terminal. In his case he likes to make sure that terminal environment is as zenful as possible, which lets him achieve greater focus and, ultimately, become more productive.

To make that happen he uses zsh with a specific set of themes and plugins chosen to do two things at once: reduce the amount of information on screen, while still providing powerful interactive features. That combination is the whole thesis of the video. It brings calm into the shell environment while also preventing the loss of momentum caused by interrupts, the two classic ones being forgetting a CLI command and having to go searching through shell history for a command you used once.

And the third constraint, the one that quietly rules out the obvious solution: all of this is done in a way that keeps zsh initialization times incredibly fast, which lets him create multiple terminal windows with no noticeable delay. That constraint is why Oh My Zsh never gets installed in this build, even though several of its plugins do get used. More on that at 14:38.

So the video is a full walkthrough of how he sets up his own zsh environment to achieve what he calls the ultimate zenful experience.

.zshrc load order, and why each stage sits where it does 1. Powerlevel10k instant prompt block must stay at the very top: it paints a prompt before the rest of the file has finished loading 2. ZINIT_HOME + clone if missing + source zinit.zsh the config installs its own plugin manager, so it carries to a fresh machine unchanged 3. zinit ice depth=1; zinit light romkatv/powerlevel10k the prompt itself, shallow cloned 4. the big three + fzf-tab zsh-syntax-highlighting, zsh-completions, zsh-autosuggestions, Aloxaf/fzf-tab order matters inside zsh: syntax highlighting wants to be loaded before autosuggestions 5. zinit snippet OMZP::git, sudo, archlinux, aws, kubectl, kubectx, command-not-found Oh My Zsh plugins, individually, without Oh My Zsh 6. autoload -Uz compinit && compinit 7. zinit cdreplay -q cdreplay must come AFTER compinit: it replays the completions the plugins cached 8. source ~/.p10k.zsh, keybindings, history options, zstyle completion styling, aliases plain settings, no network, no subprocesses 9. eval "$(fzf --zsh)" and eval "$(zoxide init --cmd cd zsh)" shell integrations last: each one shells out, so they are the only real startup cost
Figure 1. The finished file is only about fifty lines, but the order is load bearing in three places: the instant prompt block has to be first, zinit cdreplay -q has to be after compinit, and the two eval integrations go last because they are the only lines that spawn a process. Everything else is declarative.

Getting started: zsh, git, and a blank file (0:52)

Three prerequisites before a single config line gets written.

One, zsh installed and set as your login shell. Install it with your operating system's package manager, then set it as your user's login shell with the change shell command. His one caution: check where the path of your zsh installation actually is before you do this, because chsh wants the real path and it differs by distribution and by Homebrew versus system install.

# install with your package manager, for example
sudo pacman -S zsh          # Arch
sudo apt install zsh        # Debian and Ubuntu
brew install zsh            # macOS

# find the path, then set it as your login shell
which zsh
chsh -s /usr/bin/zsh

Two, git installed. The configuration will not work without it, because the config clones its own plugin manager and every plugin is a git repository.

Three, a clean slate. Back up any .zshrc you already have, then create a brand new empty one with touch and open it in your favorite text editor. In his case that editor is Neovim.

mv ~/.zshrc ~/.zshrc.bak
touch ~/.zshrc
nvim ~/.zshrc

That file is where all of the zsh configuration is going to live. First thing into it: a plugin manager.

The plugin manager: zinit (1:35)

There are a number of different plugin managers for zsh. For this video he uses zinit, which provides pretty much all the bells and whistles you could possibly need when it comes to plugin management.

Step one: define where zinit lives

# Set the directory we want to store zinit and plugins
ZINIT_HOME="${XDG_DATA_HOME:-${HOME}/.local/share}/zinit/zinit.git"

The value is a little complicated, so he breaks it down piece by piece.

The first part is doing something called parameter expansion. The shell first tries to expand the XDG_DATA_HOME environment variable. If that variable exists, its value is used. If the variable is not set, or is null, then the shell moves on to the second part of the expansion, which is everything after the :-. In that case it expands the HOME variable and appends /.local/share onto it.

Finally, whichever of those two won, /zinit/zinit.git gets appended onto the end. So on a machine that respects the XDG base directory spec you get $XDG_DATA_HOME/zinit/zinit.git, and on one that does not you get ~/.local/share/zinit/zinit.git. Same result, no if statement, portable across machines.

Step two: install zinit if it is not there

# Download Zinit, if it's not there yet
if [ ! -d "$ZINIT_HOME" ]; then
   mkdir -p "$(dirname $ZINIT_HOME)"
   git clone https://github.com/zdharma-continuum/zinit.git "$ZINIT_HOME"
fi

The if statement checks that there is no directory at the path in ZINIT_HOME, using the ! not operator together with -d. If that resolves to true, the config creates the directory with mkdir -p and then clones zinit down into it.

This is the single most important idea in the whole file, and he says why: it makes sure zinit is installed the first time the .zshrc is sourced, which means this configuration will easily carry over to any other machine. Copy the file to a new box, open a terminal, and the shell installs its own package manager. No bootstrap script, no manual step in a README.

Step three: source it

# Source/Load zinit
source "${ZINIT_HOME}/zinit.zsh"

Save the file. To make sure everything is working, open a new terminal window and run:

zinit zstatus

If everything is set up correctly you should see a similar result to his, maybe with a few different numbers. The package manager is now set up and ready to go, and it is time for the fun part: plugins.

The zenful prompt: Powerlevel10k (3:32)

The first plugin is the prompt. There are a number of prompt options for zsh, one of the most popular being Starship, but he goes with Powerlevel10k, which he finds gives a cleaner and more zenful experience.

A nerd font has to come first

Before Powerlevel10k can be installed, you need a nerd font set up on your system, because the prompt draws glyphs (git icons, folder icons, segment separators) that a normal font simply does not contain. He likes the JetBrains Mono nerd font, which he installs with his package manager from nerd-fonts.

# for example, on Arch
sudo pacman -S ttf-jetbrains-mono-nerd
# or on macOS
brew install --cask font-jetbrains-mono-nerd-font

Once installed, you have to make sure your terminal application is actually using it. He uses Alacritty, so he configures it in his alacritty.toml. The theme on screen throughout the video is Tokyo Night.

Installing it: one line, and what every token in it means

# Add in Powerlevel10k
zinit ice depth=1; zinit light romkatv/powerlevel10k

That line does a couple of things, so he explains all of them.

zinit ice depth=1. The ice command of zinit is, in his words, kind of confusing, but in a nutshell it lets you add arguments to the next zinit command you use. The documentation describes this as adding something to something else, such as ice to a drink, which is where the name comes from. Here it means the argument depth=1 is passed to the next command.

zinit light versus zinit load. zinit has two commands for installing packages: load and light. Both do pretty much the same thing, except load also has reporting and investigation built in. So light is, well, lighter. For a config that is optimizing startup time, light is the default choice everywhere in this file.

Where depth=1 actually goes. zinit uses git under the hood, and depth=1 is passed straight through to it. It is a shallow clone: one commit of history instead of the full repository. Less to download, less on disk.

The p10k configure wizard, and every answer he picks

Open a new terminal window and you are greeted with the Powerlevel10k configuration wizard. He walks through each step and states his choice:

Wizard questionHis answerWhy
Font and glyph rendering checksSystem dependentAnswer honestly for your setup. On the "do the icons fit between the crosses" question he had some overlap, most likely because he had scaled up his font
Prompt style4, PureThe most zenful of the bunch, though he notes Lean is also pretty nice
Prompt colorsOriginalA little more muted. He has happily used Snazzy in the past too
Non permanent content (such as how long a command took)Right sideKeeps the key information he cares about on the left
Show current timeNoShowing the clock lets him fall into clock watching instead of just getting on with work
Prompt heightTwo linesPersonal preference
Prompt spacingSparsePairs nicely with the next answer
Transient promptYesRemoves the header from previous commands, which draws his eye to the current command
Instant prompt modeVerboseShows the prompt instantly while the rest of the config is still loading, and prints any startup errors to the console rather than swallowing them
Apply changes to .zshrcYes"What's the point of adding this manually"

Transient prompt plus sparse spacing is the combination that produces the look the video is selling. Every command you already ran collapses to a single minimal line, and only the command you are typing right now carries the full prompt. The screen stops accumulating decoration.

Instant prompt is the answer to the speed constraint from the opening. Verbose mode is the recommended setting when transient prompt is on, and its virtue is honesty: if anything errors during shell startup it gets printed rather than hidden, which he thinks is a good idea.

The prompt he configures, segment by segment

/dev/zensh git:main $ npm run build /dev/zensh git:main $ ls -la

~/dev/zensh git:main 2.4s docker compose up -d

transient prompt: finished commands keep one thin line sparse spacing: a blank line before every new prompt working directory (left, always visible) git status, drawn with nerd font glyphs command duration, pushed to the right line two: nothing but the prompt character, so the command you are typing owns the eye
Figure 2. Every wizard answer he gives serves one rule: the left of the current line carries only what he needs (where he is, what branch he is on), anything non permanent gets pushed to the right, the clock is refused outright, and everything already run collapses out of the way. Two lines with sparse spacing gives the typed command a full line to itself.

What the wizard writes into your .zshrc

Once the wizard finishes, the zenful prompt is ready to use, and a bunch of configuration has been added into your .zshrc automatically. Two pieces of it, at opposite ends of the file.

At the start of the file, a block that enables the instant prompt mentioned earlier. Keep this at the top of the file so the transient prompt loads first:

# Enable Powerlevel10k instant prompt. Should stay close to the top of ~/.zshrc.
# Initialization code that may require console input (password prompts, [y/n]
# confirmations, etc.) must go above this block; everything else may go below.
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
  source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
fi

At the bottom of the file, a new line that first checks for the existence of a .p10k.zsh file and sources it if it exists:

# To customize prompt, run `p10k configure` or edit ~/.p10k.zsh.
[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh

That ~/.p10k.zsh file contains the Powerlevel10k configuration, and you can open it and modify it directly whenever you want to make a customization change. You can also call p10k configure again at any point to restart the wizard.

The big three plugins (7:59)

With the zenful prompt added, on to the plugins that power up the rest of the experience. He calls these the big three, and they provide the foundation for the setup: syntax highlighting, tab completions, and autosuggestions.

1. Syntax highlighting

zinit light zsh-users/zsh-syntax-highlighting

zsh-syntax-highlighting does pretty much what it says on the tin: it enables nice syntax highlighting for your commands as you type them. In practice it is also a live typo checker, since a command that does not exist is colored differently from one that does, before you ever press Enter.

2. Completions

zinit light zsh-users/zsh-completions

zsh-completions provides autocomplete functionality for a number of different CLI tools. But adding the plugin is not enough on its own: you also need to tell zsh to automatically load your completions whenever it starts.

# Load completions
autoload -Uz compinit && compinit

Now, opening a new terminal window and starting to type a command, pressing Tab shows any completions associated with it. You can see which tools the plugin provides completions for on its GitHub repository, and while it covers a lot of tools, it does not cover every single one. Adding the missing ones is what section 14:38 is about.

3. Autosuggestions

zinit light zsh-users/zsh-autosuggestions

zsh-autosuggestions is, he believes, the most popular zsh plugin there is. It provides autosuggestions based on your command history, similar to what the fish shell provides. Unlike the fish implementation though, he finds the zsh one a lot more configurable.

To make accepting an autosuggestion a little bit easier, he likes to bind it to Ctrl+F:

bindkey '^f' autosuggest-accept

But personally he prefers to just set his keybindings to emacs mode instead, which not only sets up Ctrl+F for accepting a suggestion but also brings along a whole set of other useful bindings:

# Keybindings
bindkey -e

What emacs mode gives you, in his list:

KeybindingWhat it doesWhere it comes from
Ctrl+FAccept the autosuggestion, or if there is no suggestion, move the cursor forward one characterbindkey -e
Ctrl+BMove backwards through the promptbindkey -e
Ctrl+AJump to the start of the promptbindkey -e
Ctrl+EJump to the end of the promptbindkey -e
Ctrl+PCycle backwards through history, and later in the video rebound to prefix matched searchbindkey -e, then history-search-backward
Ctrl+NCycle forwards through history, and later rebound the same waybindkey -e, then history-search-forward
Ctrl+RReverse search, upgraded to a fuzzy finding windoweval "$(fzf --zsh)"
TabCompletion, upgraded to an interactive searchable menu with previewsAloxaf/fzf-tab

The number of hotkeys emacs mode provides is pretty substantial, too much for one video, and he offers to make a separate video on it if people ask in the comments.

PluginWhat it addsCost
zsh-syntax-highlightingColors commands as you type; a wrong command is visibly wrong before you press EnterNegligible, pure zsh
zsh-completionsTab completion definitions for a large set of CLI tools that zsh does not shipNeeds compinit, which is the one genuinely slow builtin here
zsh-autosuggestionsFish style inline suggestion from history, accepted with Ctrl+FNegligible, and more configurable than fish's own
Aloxaf/fzf-tabReplaces the default completion menu with an interactive fzf window, searchable, with previewsRequires fzf installed; must be loaded after the big three
romkatv/powerlevel10kThe prompt itself, plus instant prompt and transient promptInstant prompt makes it feel free even when it is not
OMZP snippetsIndividual Oh My Zsh plugins (git aliases, sudo, kubectl and friends) fetched by URLOne file each, versus Oh My Zsh's whole framework
Oh My Zsh (not used)Would give all of the above in one installQuite bloated, with a noticeable impact on shell startup times

Making history persist, and searching it properly (10:02)

With autosuggestions enabled there is immediately a problem. Open a new terminal window and none of the commands from your other shell session are being suggested to you. For command history to persist between sessions, a few options have to be set up and enabled.

He adds them and explains each one:

# History
HISTSIZE=5000
HISTFILE=~/.zsh_history
SAVEHIST=$HISTSIZE
HISTDUP=erase
setopt appendhistory
setopt sharehistory
setopt hist_ignore_space
setopt hist_ignore_all_dups
setopt hist_save_no_dups
setopt hist_ignore_dups
setopt hist_find_no_dups

Line by line:

Open a new window and historical commands are now suggested, and you can cycle through them with Ctrl+P and Ctrl+N.

The refinement: prefix matched history search

There is one more thing he likes to configure. Start typing curl, then search back through history, and the default behavior shows other commands unrelated to curl. Not useful.

The fix is to rebind Ctrl+P and Ctrl+N to the prefix aware widgets:

bindkey '^p' history-search-backward
bindkey '^n' history-search-forward

Now open another terminal window, start typing curl, and press Ctrl+P: you only get results that match that prefix. This is a small change with a large effect on momentum, and it is the exact interrupt he named in the opening (having to go hunting through history for a command you once used).

With that, the foundation of completions, autosuggestions, and command history is configured. Now for the powerful improvements to the completions UI.

Basic completion styling (12:17)

Fixing case sensitivity

There is one issue with the current completion setup. In a terminal window, type cd followed by a capital D and press Tab: it shows completions for the three directories matching in his home folder. Try the same thing with a lowercase d and nothing matches at all. That is because by default the autocompletion is case sensitive.

The fix is one zstyle line configuring the completion matcher list so that lowercase characters also match uppercase ones:

# Completion styling
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Za-z}'

Test it again and lowercase d now autocompletes the capitalized directories.

Adding color

The other thing you may have noticed in the autocomplete results is that there is no color to them. Ideally any files or directories should be colored exactly as if you were running ls --color.

First, create an alias so ls always means ls --color:

alias ls='ls --color'

Then hand the same color database to the completion system:

zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}"

The ${(s.:.)LS_COLORS} part is a zsh parameter expansion flag that splits the LS_COLORS variable on the : character, turning that one long colon separated string into the array zstyle expects. With that, completions get the same colors as ls --color.

fzf and the advanced completion menu (13:29)

Basic styling done, time to turn it up a notch and add an interactive fuzzy finding menu for both completions and reverse searching. The tool for that is fzf, a fuzzy finder for the terminal, and it is incredibly powerful.

Install fzf and wire in the shell integration

Install it with your package manager, then add the shell integration line to your config:

# Shell integrations
eval "$(fzf --zsh)"

That single line enables a few things, and his favorite is fuzzy finding on reverse search, invoked with Ctrl+R. He shows the comparison directly: the default zsh reverse search versus the fzf window. As well as displaying results in a fuzzy finding window, it lets you navigate them with Ctrl+P and Ctrl+N, consistent with the keybindings already set up. He finds this a much better experience than the default menu.

Bring the same window to tab completion: fzf-tab

That better menu can be brought to the completions menu too. It needs one more plugin, fzf-tab:

zinit light Aloxaf/fzf-tab

And then one line to make things work a little nicer, disabling the default zsh completion menu so the two do not fight:

zstyle ':completion:*' menu no

Now open another window and start a tab completion: it loads an interactive fzf window that you can both navigate and search through.

Previews in the completion window

There is more customization available on that window, and the one he adds is a preview of directory contents when running the cd autocompletion:

zstyle ':fzf-tab:complete:cd:*' fzf-preview 'ls --color $realpath'

The $realpath variable is fzf-tab's placeholder for whatever candidate is currently highlighted in the menu, so as you move through candidates the preview pane runs ls --color on each one in turn. You are looking inside directories before you commit to entering them.

fzf-tab is incredibly powerful and can do a lot more than this, but he saves that for another video.

More completions: Oh My Zsh plugins, without Oh My Zsh (14:38)

Back at 7:59 he promised to show how to add completions for CLI tools that zsh-completions does not cover. The best place to find these is the plugins directory of the Oh My Zsh repository.

But, as you may have noticed, he has actively chosen not to use Oh My Zsh, mainly because he finds it quite bloated and it has a noticeable impact on shell startup times. That is the tension the section resolves: the plugins are good, the framework around them is the thing he does not want.

The resolution is zinit's snippet functionality, which lets you download and install a plugin via a URL, or, in the case of Oh My Zsh, via a defined namespace. OMZP:: expands to the Oh My Zsh plugins URL, and whatever follows is the path to the plugin.

zinit snippet OMZP::git

That one line pulls in the git plugin, which provides a number of aliases for various git commands. Open another terminal window and the git aliases are available. One file fetched, no framework installed.

The other snippets he likes to add:

# Add in snippets
zinit snippet OMZP::git
zinit snippet OMZP::sudo
zinit snippet OMZP::archlinux
zinit snippet OMZP::aws
zinit snippet OMZP::kubectl
zinit snippet OMZP::kubectx
zinit snippet OMZP::command-not-found

What each of them buys you: git gives the alias set, sudo lets you press Escape twice to prefix the current or previous command with sudo, archlinux adds pacman and AUR helpers, aws and kubectl and kubectx add completions and helpers for those CLIs, and command-not-found suggests the package to install when you type a command your system does not have.

The one ordering rule: cdreplay goes under compinit

With the snippets added, one more line goes underneath where compinit is loaded:

zinit cdreplay -q

This is used by zinit to replay all cached completions, and it is recommended by the zinit documentation. The reason it has to come after compinit is that the plugins and snippets loaded above register compdef calls, zinit captures those instead of executing them, and cdreplay is what runs them back once the completion system actually exists. The -q flag keeps it quiet. Put this line above compinit and completions from your snippets silently do not work.

A better cd: zoxide (16:16)

Very close to the end, one last thing he likes to add: zoxide.

If you are unaware, zoxide lets you easily navigate around your filesystem using fuzzy matching, which saves him a load of time and lets him stay focused. It remembers the directories you visit and ranks them, so cd zen jumps straight to ~/dev/projects/zensh without typing the path. He has a whole separate video on zoxide.

eval "$(zoxide init --cmd cd zsh)"

The --cmd cd flag is the aggressive part of that line: instead of learning a new command like z, zoxide replaces cd itself, so muscle memory keeps working and every plain cd you type feeds the ranking database.

Because cd is now a zoxide function rather than the builtin, the fzf-tab preview configured earlier no longer matches it, so one more completion style is needed for previews to work with zoxide as well:

zstyle ':fzf-tab:complete:__zoxide_z:*' fzf-preview 'ls --color $realpath'

__zoxide_z is the internal function name zoxide installs behind the cd alias, which is why the zstyle pattern targets that rather than cd.

The environment specific tail

All that remains is anything custom and specific to your own environment: any aliases for commonly used commands, or any directories you want to add to your shell path.

# Aliases
alias ls='ls --color'
alias vim='nvim'
alias c='clear'

And if you are on macOS, you also want the line that makes any Homebrew installed apps available on your path:

# macOS only
eval "$(/opt/homebrew/bin/brew shellenv)"

With that, the ultimate zenful zsh setup is configured.

Dotfiles (17:02)

Now is a good time to add your new configuration files into your dotfiles repository. If you do not have one set up, he points at another video of his showing how to set up your own dotfiles repo.

The two files worth committing from this build are ~/.zshrc and ~/.p10k.zsh. Everything else, zinit itself and every plugin, is reconstructed on first launch by the bootstrap block at the top of the file, which is precisely why that block was written the way it was. His finished version of the config is published as zensh. The tmux config visible alongside it in the video comes from his main channel, @dreamsofcode.

The complete .zshrc

Everything above, assembled in order. This is the whole file.

# Enable Powerlevel10k instant prompt. Should stay close to the top of ~/.zshrc.
# Initialization code that may require console input (password prompts, [y/n]
# confirmations, etc.) must go above this block; everything else may go below.
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
  source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
fi

# Set the directory we want to store zinit and plugins
ZINIT_HOME="${XDG_DATA_HOME:-${HOME}/.local/share}/zinit/zinit.git"

# Download Zinit, if it's not there yet
if [ ! -d "$ZINIT_HOME" ]; then
   mkdir -p "$(dirname $ZINIT_HOME)"
   git clone https://github.com/zdharma-continuum/zinit.git "$ZINIT_HOME"
fi

# Source/Load zinit
source "${ZINIT_HOME}/zinit.zsh"

# Add in Powerlevel10k
zinit ice depth=1; zinit light romkatv/powerlevel10k

# Add in zsh plugins
zinit light zsh-users/zsh-syntax-highlighting
zinit light zsh-users/zsh-completions
zinit light zsh-users/zsh-autosuggestions
zinit light Aloxaf/fzf-tab

# Add in snippets
zinit snippet OMZP::git
zinit snippet OMZP::sudo
zinit snippet OMZP::archlinux
zinit snippet OMZP::aws
zinit snippet OMZP::kubectl
zinit snippet OMZP::kubectx
zinit snippet OMZP::command-not-found

# Load completions
autoload -Uz compinit && compinit

zinit cdreplay -q

# To customize prompt, run `p10k configure` or edit ~/.p10k.zsh.
[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh

# Keybindings
bindkey -e
bindkey '^p' history-search-backward
bindkey '^n' history-search-forward

# History
HISTSIZE=5000
HISTFILE=~/.zsh_history
SAVEHIST=$HISTSIZE
HISTDUP=erase
setopt appendhistory
setopt sharehistory
setopt hist_ignore_space
setopt hist_ignore_all_dups
setopt hist_save_no_dups
setopt hist_ignore_dups
setopt hist_find_no_dups

# Completion styling
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Za-z}'
zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}"
zstyle ':completion:*' menu no
zstyle ':fzf-tab:complete:cd:*' fzf-preview 'ls --color $realpath'
zstyle ':fzf-tab:complete:__zoxide_z:*' fzf-preview 'ls --color $realpath'

# Aliases
alias ls='ls --color'
alias vim='nvim'
alias c='clear'

# Shell integrations
eval "$(fzf --zsh)"
eval "$(zoxide init --cmd cd zsh)"

Two lines to add only if they apply to you: eval "$(/opt/homebrew/bin/brew shellenv)" on macOS, and bindkey '^f' autosuggest-accept if you would rather bind that one key than switch the whole shell to emacs mode with bindkey -e.

Key takeaways

Chapters

Notable quotes

"I like to ensure that my terminal environment is as zenful as possible, which enables me to achieve greater focus and ultimately become more productive." (0:00)

"A certain set of themes and plugins designed to both reduce the amount of information on screen whilst also providing powerful interactive features." (0:07)

"All of this is done in a way that keeps my initialization times of zsh incredibly fast, which allows me to create multiple terminal windows with no noticeable delay." (0:30)

"All of this makes sure that zinit is installed the first time the .zshrc is sourced, which means this configuration will easily carry over to any other machine." (2:52)

"The ice command of zinit is kind of confusing, but in a nutshell it enables you to add arguments to the next zinit command you'll use. The documentation describes this as adding something to something else, such as ice to a drink, which is where the origin of the name comes from." (4:16)

"Both of them pretty much do the same thing, except the load command also has reporting and investigation built in, so the light command is, well, lighter." (4:47)

"For the prompt style I chose number four, which is called Pure. For me it's the most zenful out of the bunch, although the lean one is also pretty nice." (5:40)

"When it comes to showing the current time, this is something I personally choose not to, as doing so can enable me to perform clock watching instead of just getting on with work." (6:10)

"This couples quite nicely with enabling the transient prompt, which removes the header from previous commands, helping to draw my eye to what the current command is." (6:28)

"The instant prompt is a pretty awesome feature of Powerlevel10k. It'll basically show the prompt instantly even whilst your zsh configuration is still loading." (6:41)

"Go ahead and select yes for this, because, well, what's the point of adding this manually." (7:04)

"This plugin does pretty much what it says on the tin." (8:13)

"zsh-autosuggestions, which I believe is the most popular zsh plugin. This plugin provides autosuggestions based on your command history, similar to what the fish shell provides. However, unlike the fish implementation, I find the zsh one to be a lot more configurable." (8:56)

"Let's set the hist ignore space option, which allows us to prevent a command from being written to the history file by adding a space before it. This is useful to prevent any sensitive information from being saved in your history file." (11:03)

"By default the autocompletion is case sensitive." (12:38)

"As you may have noticed, I've actively chosen to not use Oh My Zsh, mainly because I find it quite bloated and it has a noticeable impact on shell startup times." (14:57)

"zoxide allows you to easily navigate around your file system using fuzzy matching, which saves me a load of time and allows me to stay focused." (16:20)

Resources mentioned

The config itself

Shell and plugin manager

Prompt

The big three and friends

Fuzzy finding and navigation

Snippets and the framework he skips

Terminal, theme, editor, and the rest of the environment

Full transcript
[00:00:00] if you're like me then you probably spend a lot of time working inside of your terminal in my case I like to ensure that my terminal environment is as zenful as possible which enables me to achieve greater focus and ultimately become more productive in order to make that happen I use zshell with a certain set of themes and plugins designed to both reduce the amount of information on screen whilst also providing powerful interactive features this helps to bring calm into my shell environment whilst also preventing any loss of momentum caused by interrupts such as for getting [00:00:30] CLI commands or needing to search through my shell history for a command I once used all of this is done in a way that keeps my initialization times of zshell incredibly fast which allows me to create multiple terminal windows with no noticeable DeLay So in this video I'm going to show you how I set up my own Zell environment to achieve the Ultimate zenful Experience to get started you'll first want to make sure you have Zell installed on your system and that it's your main login shell you can do this by installing Zell as your operating [00:01:00] systems package manager once installed you can then set it to be your users's login shell using the change shell command make sure to check where the path of your zshell installation is before doing this next in order for this configuration to work you'll need to make sure you have git installed on your system as well with our dependencies added the last thing you'll want to do is back up any zshell RC you may already have then go ahead and create a brand new one using the touch command afterwards you can open it up inside of your favorite text editor in my case case I'm using neovim this file is where [00:01:32] all of our zshell configuration is going to live with the first thing we're going to configure being a plug-in manager when it comes to zshell there are a number of different plug-in managers however for this video we're going to use Z init which provides pretty much all the bells and whistles you could possibly need when it comes to plug-in Management in order to add Z inits we first need to Define where it's going to live we can do this with the following line which creates a new environment variable called Z in Itor home the value of this nvar is a little bit complicated [00:02:02] so let's break it down the first part of this value is performing something called parameter expansion we're first trying to expand the xdg data home nvar and if it exists we'll use that value if the nvar isn't set or is null then we'll actually move on to the second part of this expansion which is everything after the colon dash in this case we're then expanding the home mvar and appending on the sl. lo/ share finally we're then appending on the /z in itzin it.get to [00:02:32] whatever we've expanded with our Z init home andar defined the next thing to do is to check to see if it already exists we can do this with the following if statement which is checking that there is no directory at the Z init home enva as defined with the not operator and the Dash D if this resolves the true then we want to create this directory using the make dear command with the- P flag followed by cloning down Z init into our Z init home envar directory all of this makes sure that Z init is installed the first time the zshell RC is sourced [00:03:03] which means this configuration will easily carry over to any other machine Now All That Remains is to go ahead and Source our Z init file that we just downloaded go ahead and save this file and let's make sure everything is working correctly we can do this by opening up a new terminal window and typing in the Z init Z status commands if everything is set up correctly you should see a similar result to what I have maybe with a few different numbers and with that our package manager is now set up and ready to go now comes the fun part adding in some plugins the first [00:03:33] plug-in we're going to add is our zenful prompt when it comes to Zell there are a number of different prompt options available with one of the most popular ones being starship.com called power level 10K which I find gives a little bit more of a cleaner and zenful experience before we can install it however we first need to get a nerd font set up on our system for me I like to use the jetbrains Monon nerd font [00:04:03] which I can install using my package manager once installed you'll need to make sure your terminal application is using it if you're using elac like I am then you can configure this in your elac dotmmo with our nerd font added and set up we can now go ahead and install power level 10K to do so with Z in it is rather simple all we need to do is add in the following line however this line is doing a couple of things so I think it's worthwhile explaining what those are the first part of the line is z init ice depth equals 1 the ice command of Z [00:04:33] init is kind of confusing but in a nutshell it enables you to add arguments to the next Z in its command you'll use the documentation describes this as adding something to something else such as ice to a drink which is where the origin of the name comes from in this case that means we're passing the argument of depth equals 1 to the next command which is the Z init light command z in it has two commands for installing packages Z in its load and z in its light both of them pretty much do the same thing except the load command [00:05:03] also has reporting and investigation built in so the light command is well lighter additionally z in it makes use of git under the hood which is where the depth equals 1 argument is being passed into hopefully that makes some sense and feel free to watch that part of the video if you ever need a refresher let's move on to the next part which is getting power level 10K configured to kick that off go ahead and open up a new terminal window and you'll be greeted with the power level 10K configuration wizard where you get to customize it to your liking let's go through each step [00:05:33] and I'll tell you which options I choose the first of these are pretty easy to answer and will be dependent on your own system provided you installed and set up your nerd font when it came to the question about icons fitting between the two crosses in my case there was some overlap but most likely due to the fact that I had scaled up my font for the prompt style I chose number four which is called Pure for me it's the most sful out of the bunch although the lean one is also pretty nice when it comes to the The Prompt colors I went for the original which are a little bit more muted although in the past I've happily [00:06:04] used snazzy as well when it comes to non-permanent content such as the amount of time a command took I like to keep that on the right side again this allows me to keep the key information I care about on the left when it comes to showing the current time this is something I personally choose not to as doing so can enable me to perform clock watching instead of just getting on with work when it comes to the prompt Heights this is going to be pretty much a personal preference but in my case I like to keep this as two lines next up is prompt spacing which in my case I [00:06:34] prefer to keep sparse this couples quite nicely with enabling the transient PR which removes the header from previous commands helping to draw my eye to what the current command is lastly is setting up instant prompt mode the instant prompt is a pretty awesome feature of power level 10K it'll basically show The Prompt instantly even whilst your zshell configuration is still loading the recommended mode for transient prompt is verose which means if any errors occur during the shell startup they'll be printed to the console personally I think this is a good idea so let's go ahead and select that option lastly it's [00:07:06] going to ask if we want the changes applied to our zshell RC go ahead and select yes for this because well what's the point of adding this manually once that's done your awesome zenful prompt is now ready to use congratulations and not only that but we also have a bunch of configuration added into our zshell RC if we take a look at this configuration you'll see we have a couple of lines at the start of our file this is to enable the the transient prompt which I mentioned earlier you'll want to make sure you keep this at the top of the file so that the transient prompt is loaded first then at the [00:07:37] bottom of our configuration you'll see we have a new line this line first checks for the existence of a p10k do zshell file and then sources it if it exists this file contains our power level 10K configuration which we can actually open up and modify if we ever want to make some customization changes Additionally you can also call the p10k configure command in order to restart the configuration wizard now that we have our zenful prompt added let's move on to some other plugins to power up our Zell experience the first plugins I like to add are what I call [00:08:08] the big three and are used to provide the foundation for our setup these are syntax highlighting tab completions and auto suggestions let's begin with syntax highlighting which we can add in using the following line This plugin does pretty much what it says on the tin and enables nice syntax highlighting for our commands the next plugin to add is zshell completions which provides autocomplete functionality for a number of different CLI tools we can add this using the following line however we also need to tell Zell to automatically load [00:08:39] our completions whenever it starts which is done as follows now when I open up a new terminal window and start typing out a command I can press the Tab Key to see any completions associated with it you can see which tools this plug-in provides completions for on the GitHub repo and whilst it does cover a lot of tools it doesn't cover every single one however I'll show you how to add other comp completions later on the Last of The Big Three is Zell Auto suggestions which I believe is the most popular Zell plug-in this plug-in provides Auto suggestions based on your command [00:09:10] history similar to what the fish shell provides however unlike the fish implementation I find the zshell one to be a lot more configurable to make accepting Auto suggestions just a little bit easier I like to bind it to the control F key you can do so by adding in the following line however personally I prefer to just set my key bindings to email Max mode which not only sets up the control F key for accepting a suggestion but also provides a number of other useful key bindings such as control B for moving backwards through the prompt contrl f for moving forwards [00:09:41] if there's no order suggestion contrl a to jump to the start of the prompt and contr E to jump to the end Additionally you can also cycle backwards and forwards through your auto suggestion history using contrl p andr n respectively the number of hot keys that emac mode provides is pretty substantial too much for this one video if you'd like another video on that however then let me know in the comments down below with that the Autos suggestion plugin is enabled however we currently have a bit of an issue you'll notice if I open up a new terminal window none of the commands from my other shell session are being [00:10:12] suggested to me in order for our Command history to persist between sessions we need to set up and enable a few options inside of our configuration to do so we're going to add in a few lines which I'll explain one by one first of all is hist size which we're setting to be 5,000 this sets the the number of commands we want to be saved inside of our history feel free to increase or decrease this depending on your preference the second variable sets our history file which is the file that's used to store all of our historical commands the next variable is saved hist [00:10:43] which needs to be the same size as hist size the next variable is his dup which we're setting to be arrays this will arras any duplicates inside of our history file next up is going to be our Zell options the first one is the append history option which causes Zell to append any commands to the history file rather than overwriting it next we're setting the share history option which will share our Command history across all zshell sessions at the same time afterwards let's set the hist ignore space option which allows us to prevent [00:11:13] a command from being written to the history file by adding a space before it this is useful to prevent any sensitive information from being saved in your history file next up we have the hist ignore all dupes hist save no dupes and hist ignore dupes these are used to prevent any duplicate commands from being saved inside of our history lastly we have the hist find no dupes option which will prevent any duplicates from being shown to us inside of our historical search now if I open up a new window you can see that my historical commands are being suggested and I'm [00:11:44] able to cycle through them using contrl p and crln however there's another thing I like to configure if I start typing out the curl command and then search through my historical suggestions you'll see that it shows other commands not related to curl we can resolve this by heading over to our zshell r and adding in the following lines which binds the contrl p and contrl N keys to history search backwards and history search forwards respectively now if I open up another terminal window and begin typing out the curl command again if I press contrl P to start cycling through my history you'll see I only receive [00:12:15] results that match that prefix with that we have the foundation for completions audo suggestions and command history configured now we can begin adding in some more powerful improvements to our completions UI first things first we need to complete one issue with our current completion setup if I head on over to a terminal window and start typing out the CD command followed by a capital D when I start pressing tab you'll see it will show completions for the three directories that match inside of my home folder however if I try to do this with a lowercase D then nothing [00:12:45] will match that's because by default the autoc completion is case sensitive fortunately we can resolve this with the following line which configures a z style for the completion matcher list causing lowercase characters to also match with uppercase ones as well now if I test this out you can see that we can autocomplete on the lowercase D one thing you may have noticed in the autocomplete results is that there's no color to them ideally we want any files or directories to be colored as if we were using the ls-- color command to begin let's first go ahead and create an [00:13:15] alias for the ls command 2.2 ls-- color then we can add in the following line to enable this for our Z style completion as well with that the completions will also have colors applied just like they would with ls-- color okay now that we have some basic styling for completions added let's turn it up a notch and add in an interactive fuzzy finding menu for completions and reverse searching to achieve this we're going to use FCF which is a fuzzy finding tool for the terminal and Incredibly powerful to begin you'll need to make sure you have [00:13:46] FCF installed on your system which you should be able to do using your package manager once installed we can then set up the FCF shell integration by adding in the following line to our zshell configuration this will enable a few things but one of my favorites is the fuzzy finding on our reverse search which you can invoke using control and R for comparison this is what it looks like without FCF enabled as well as displaying the results in a fuzzy finding window it'll also allow us to navigate using crl p and crln personally I find this to be a much better experience than the default menu which [00:14:18] we can actually bring to our completions menu as well to do so we need to add a new plug-in with Z in it for FCF tab which we can do with the following line then to make things work a little nicer add in the following line to disable the default zshell completion menu now if I open up another window and start a tab completion you'll see that this loads an interactive FCF window which we can both navigate and search through this is awesome but we can also add some even more customization to this window such as displaying a preview of our directories when we run the CD Auto [00:14:48] completion this is enabled by adding in the following Z style configuration FCF tab is incredibly powerful and we can do a lot more with it however I'm going to save that for another video whilst we're on the subject of completions I mentioned earlier I'd show you how to add plugins for other CLI tools the best place to find these is in the plugins directory of the omiz zshell repository however as you may have noticed I've actively chosen to not use omiz zshell mainly because I find it quite bloated and it has a noticeable impact on shell startup times fortunately we can add [00:15:19] these plugins individually using Z inits snippet functionality which allows us to download and install a plugin via a URL or in the case of om zshell a defined namespace let's use this to install the git plug-in from the omiz zshell repository which provides a number of different aliases for various git commands to do so all we need to do is add in the following line into our zshell RC this line uses the OMP namespace which points to the omiz Shell plugins URL followed by the path to the [00:15:49] plugin in our case get now if I open up another terminal window you can see that I have the git aises available the other Snippets I like to add are the pseudo archland AWS Cube CTL Cube context and the command not found plugins as well as these go ahead and add in the Z init CD replay - Q command underneath where we load our comp init this is used by Z init to replay all cached completions which is recommended by the documentation we're really close to the end there's just one last thing I like [00:16:19] to add into my configuration Z oxide if you're unaware Z oxide allows you to easily navigate around your file system using fuzzy matching which saves me a load of a time and allows me to stay focused I've done a whole another video on Z oxide if you're interested so go ahead and check that out we can add Z oxide to our configuration using the following line additionally we need to add another completion style in order for previews to work with Z oxide as well All That Remains now is adding anything custom that's specific to your own environment such as any custom [00:16:49] aliases for commonly used commands or any directories you want to add to your Shell Path if you're using Mac OS you're also going to want to add in the following line which is needed to make any home brw installed apps available on your path with that we've managed to configure the ultimate zenful zshell setup now is a good time to go ahead and add your new configuration files into your dot files repository if you don't have one set up however then don't worry I have another video showing you how you can set up your own do files repo which you can watch right here