After some years of using the great one and only zsh
shell, I have accumulated a few plugins in my
configuration. My plugin manager of choice has been
antibody which is written in Go and
consists of a single binary. It does everything I want and stays mostly out of
my way, but the setup involves downloading or compiling a binary and placing it
somewhere in your
This is fine if you have only one device with your shell configured, but if you want to manage and deploy your dotfiles automatically, it introduces unnecessary complexity and extra work.
I manage all my dotfiles with ansible, setting up antibody with all of it’s
plugins is defined in a dedicated ansible
deploying the dotfiles to a new machine, this role has often been the one to
cause problems and involve manual fixing. I tried various approaches, the last
one being to run the
install_antibody.sh script that I put in the repository
of my ansible role.
What I really want, is to have as little moving parts as possible for my shell setup. It should just work™ and just involve starting the ansible playbook, me getting a coffee and coming back to a fully configured shell the way I have it setup on all my other devices.
A few days ago I saw an announcement on reddit about a new plugin manager, written in pure zsh code and decided to give it a try.
Znap is roughly 4 kilobytes of source code that does everything you could ask for from a plugin manager and nothing that you don’t ask for.
The installation consists of cloning the repository and sourcing it from your
.zshrc. Plugins are simply cloned from via some handy aliases it provides.
Here is the repository for those not knowing how google works.
Create a folder to hold all your plugins and znap itself
suggested, but you can use anything you want. In it clone the managers
mkdir ~/.zsh-plugins cd ~/.zsh-plugins git clone https://github.com/marlonrichert/zsh-snap.git
That’s it. Now just source the manager at the top of your
.zshrc so it is
loaded before any of the functions provided by it are used and restart your
# ~/.zshrc source ~/.zsh-plugins/zsh-snap/znap.zsh
To install a plugin you could manually clone it to your newly created
~/.zsh-plugins folder, but znap provides a function to do it for you that
places it in the correct directory.
I currently use the following plugins
From on-my-zsh and prezto I only want to include certain parts and not the complete plugin eco-system
All of them can be installed with a single command (of course you could also run multiple commands to split it up)
znap clone \ [email protected]:zsh-users/zsh-completions.git \ [email protected]:zsh-users/zsh-syntax-highlighting.git \ [email protected]:mafredri/zsh-async.git \ [email protected]:rupa/z.git \ [email protected]:robbyrussell/oh-my-zsh.git \ [email protected]:sorin-ionescu/prezto.git \ [email protected]:sindresorhus/pure.git \ [email protected]:ael-code/zsh-colored-man-pages.git \ [email protected]:momo-lab/zsh-abbrev-alias.git \ [email protected]:Aloxaf/fzf-tab.git
Znap will download all plugins to the
.zsh-plugins directory. At this point
you only have to source the folders of each plugin you want to use from your
~/.zshrc. For me this looks like this:
source ~/.zsh-plugins/zsh-snap/znap.zsh znap source zsh-completions znap source zsh-syntax-highlighting znap source zsh-async znap source z znap source zsh-colored-man-pages znap source zsh-abbrev-alias znap source fzf-tab # From Oh-my-ZSH znap source oh-my-zsh lib/completion # From Prezto znap source prezto znap source prezto \ modules/helper \ modules/completion \ modules/environment \ modules/terminal \ modules/editor \ modules/history \ modules/directory \ modules/syntax-highlighting \ modules/zsh-history-substring-search \ modules/utility fpath+=( $(znap path prezto) ) # Pure prompt znap source pure fpath+=$(znap path pure) autoload -Uz promptinit && promptinit prompt pure
That’s all! Everything worked out of the box with the above configuration. My shell looks and behaves exactly like it did before, with the difference of being extremly portable and probably working on any system that has zsh installed.
I will update my ansible role for zsh to use znap, which should be only a matter
of using the git
~/.zshrc file like I did before. No compiling, no dependencies and
hopefully no more broken shells.
Thanks to Marlon Richert, the author of znap, leave him a star on GitHub!