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.
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 question | His answer | Why |
|---|---|---|
| Font and glyph rendering checks | System dependent | Answer 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 style | 4, Pure | The most zenful of the bunch, though he notes Lean is also pretty nice |
| Prompt colors | Original | A little more muted. He has happily used Snazzy in the past too |
| Non permanent content (such as how long a command took) | Right side | Keeps the key information he cares about on the left |
| Show current time | No | Showing the clock lets him fall into clock watching instead of just getting on with work |
| Prompt height | Two lines | Personal preference |
| Prompt spacing | Sparse | Pairs nicely with the next answer |
| Transient prompt | Yes | Removes the header from previous commands, which draws his eye to the current command |
| Instant prompt mode | Verbose | Shows 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 .zshrc | Yes | "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.
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:
| Keybinding | What it does | Where it comes from |
|---|---|---|
Ctrl+F | Accept the autosuggestion, or if there is no suggestion, move the cursor forward one character | bindkey -e |
Ctrl+B | Move backwards through the prompt | bindkey -e |
Ctrl+A | Jump to the start of the prompt | bindkey -e |
Ctrl+E | Jump to the end of the prompt | bindkey -e |
Ctrl+P | Cycle backwards through history, and later in the video rebound to prefix matched search | bindkey -e, then history-search-backward |
Ctrl+N | Cycle forwards through history, and later rebound the same way | bindkey -e, then history-search-forward |
Ctrl+R | Reverse search, upgraded to a fuzzy finding window | eval "$(fzf --zsh)" |
Tab | Completion, upgraded to an interactive searchable menu with previews | Aloxaf/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.
| Plugin | What it adds | Cost |
|---|---|---|
| zsh-syntax-highlighting | Colors commands as you type; a wrong command is visibly wrong before you press Enter | Negligible, pure zsh |
| zsh-completions | Tab completion definitions for a large set of CLI tools that zsh does not ship | Needs compinit, which is the one genuinely slow builtin here |
| zsh-autosuggestions | Fish style inline suggestion from history, accepted with Ctrl+F | Negligible, and more configurable than fish's own |
| Aloxaf/fzf-tab | Replaces the default completion menu with an interactive fzf window, searchable, with previews | Requires fzf installed; must be loaded after the big three |
| romkatv/powerlevel10k | The prompt itself, plus instant prompt and transient prompt | Instant prompt makes it feel free even when it is not |
| OMZP snippets | Individual Oh My Zsh plugins (git aliases, sudo, kubectl and friends) fetched by URL | One file each, versus Oh My Zsh's whole framework |
| Oh My Zsh (not used) | Would give all of the above in one install | Quite 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:
HISTSIZE=5000sets the number of commands to keep in history. Increase or decrease it to taste.HISTFILE=~/.zsh_historyis the file used to store all of your historical commands.SAVEHIST=$HISTSIZEneeds to be the same size asHISTSIZE. Writing it as$HISTSIZErather than repeating5000means you only ever change the number in one place.HISTDUP=eraseerases any duplicates inside the history file.setopt appendhistorycauses zsh to append commands to the history file rather than overwriting it. Without this, the last shell you close wins and everything else is lost.setopt sharehistoryshares command history across all zsh sessions at the same time. This is the option that fixes the original symptom: a command typed in one window is available in another.setopt hist_ignore_spacelets you keep a command out of the history file entirely by putting a space in front of it. He calls out the real use: preventing sensitive information from being saved in your history file.setopt hist_ignore_all_dups,hist_save_no_dupsandhist_ignore_dupsall work to prevent duplicate commands being saved into history.setopt hist_find_no_dupsprevents duplicates being shown to you while searching history.
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
- The config installs its own plugin manager. The
if [ ! -d "$ZINIT_HOME" ]block means a single file, copied to a fresh machine, produces the full environment on first shell launch. There is no bootstrap script and no manual step. ${XDG_DATA_HOME:-${HOME}/.local/share}is the portability trick. Parameter expansion with:-gives a fallback without anifstatement, so the same path expression works on a machine that honors the XDG spec and one that does not.zinit lightoverzinit load, everywhere.loadadds reporting and investigation;lightskips it. Speed is a design constraint in this file, not an afterthought.iceis zinit's way of passing arguments to the next command.zinit ice depth=1handsdepth=1to git for a shallow clone.- Order is load bearing in exactly three places. The Powerlevel10k instant prompt block goes at the very top,
zinit cdreplay -qgoes undercompinit, and the twoevalintegrations go at the bottom. - Instant prompt plus transient prompt is what makes it feel zenful. One paints a prompt before the config has loaded, the other collapses every command you already ran to a thin line.
- Refusing the clock is a deliberate productivity choice. He leaves the time out of the prompt because having it there lets him fall into clock watching instead of working.
sharehistoryis the option that makes autosuggestions actually useful. Without it, a command typed in one window is invisible in the next.hist_ignore_spaceis a security setting. Prefix a command with a space and it never reaches the history file, which keeps secrets out of~/.zsh_history.- Prefix matched history search beats plain cycling. Rebinding Ctrl+P and Ctrl+N to
history-search-backwardandhistory-search-forwardmeans typingcurlthen pressing Ctrl+P shows onlycurlcommands. - You can have Oh My Zsh's plugins without Oh My Zsh.
zinit snippet OMZP::<name>fetches an individual plugin by namespace, which is his answer to a framework he considers bloated and slow to start. - fzf earns its place twice.
eval "$(fzf --zsh)"upgrades Ctrl+R reverse search, and fzf-tab pluszstyle ':completion:*' menu noupgrades the Tab menu, withfzf-previewshowing directory contents before you enter them. - zoxide with
--cmd cdreplaces the builtin. No new command to learn, and the ranking database gets fed by every navigation you already do.
Chapters
- 0:00 Intro
- 0:52 Getting Started
- 1:35 Plugin Manager
- 3:32 Zenful Prompt
- 7:59 Big Three Plugins
- 10:02 Historical Searching
- 12:17 Basic Completion Styling
- 13:29 Fzf and Advanced Completion Styling
- 14:38 More Completions
- 16:16 Better cd command
- 17:02 Dotfiles
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
- zensh, the finished config on GitHub, the exact
.zshrcthis video builds - Dreams of Autonomy on YouTube, the channel
- @dreamsofcode, his main channel, home of the tmux config seen in the video
Shell and plugin manager
- zsh, the shell
- zinit, the plugin manager the config bootstraps itself with
- zinit documentation, where
ice,lightversusload, snippets andcdreplayare specified - git, a hard dependency of the whole setup
Prompt
- Powerlevel10k, the prompt, configured through
p10k configure - Starship, the popular alternative he names and passes on
- nerd-fonts, the patched font project
- JetBrains Mono, the font he patches and uses
The big three and friends
- zsh-syntax-highlighting
- zsh-completions
- zsh-autosuggestions
- fzf-tab, the interactive completion menu
- fish shell, the origin of the inline autosuggestion idea
Fuzzy finding and navigation
Snippets and the framework he skips
- Oh My Zsh, used only as a plugin source, never installed
- Oh My Zsh plugins directory, where the
OMZP::namespace points - git plugin · sudo · archlinux · aws · kubectl · kubectx · command-not-found
Terminal, theme, editor, and the rest of the environment
- Alacritty, his terminal emulator, configured via
alacritty.toml - Tokyo Night, the color scheme used throughout the video
- Neovim, the editor he writes the config in
- Homebrew, for the macOS
brew shellenvline - XDG Base Directory Specification, the spec behind
XDG_DATA_HOMEandXDG_CACHE_HOME


