26 July 2014
Oh-my-zsh is the Disease and Antigen is the Vaccine
oh-my-zsh is one of the most popular repositories on GitHub with 17,500+ stars. If you use zsh as your main shell, you likely have heard of oh-my-zsh or even use it.
It features “120+ optional plugins” and just as many themes for your beloved shell. It has a great default library that turns on a lot of great zsh features that make it better for new users.
However, I think that oh-my-zsh has actually become a bit harmful to the goal that it is trying to achieve.
The Problem
oh-my-zsh is a great idea but it has evolved quite a bit past its initial import into Git.
It was never “designed” to support the plugin directory that it is trying to be. The intention of providing plugins has grown beyond manageability. Let’s take a better look at the issues that oh-my-zsh has.
Git/GitHub
Using version control for something as volatile as plugins is a bit strange. While it has been working for Homebrew, Homebrew only maintains instructions on how to install each package; it obviously doesn’t contain the source of the package which is far more volatile.
Using a massive repository for this just isn’t the greatest idea for maintaining a list of plugins. Why should I have to download EVERY single plugin when I just want to use a few. Even though most plugins are a single or a few files, it just doesn’t scale and is unnecessary.
To make an analogy, it would be like having one large repository for every single Vim plugin. The thought is just absurd.
Inactivity
The other problem is that Robby Russell appears to be the only collaborator that handles pull requests and issues. Every single change must go through him and be approved. The effort just seems outrageous. The Bus factor should definitely not be that low.
At one point, there was a span of 45 days from May to nearly July in which nothing happened.
As of right now, there are nearly ~400 issues open on the oh-my-zsh repository with 70% of them being pull requests.
This isn’t a knock against Robby in anyway either. We all get busy and I know first hand that managing issues is sometimes the last thing you want to do. However it is a reason to look into alternative solutions that don’t have this dependency on a single person.
Adding Customizations
oh-my-zsh gives some pointers on adding your own customizations. What does it suggest?
It says to add your own files into the custom/
directory. That sounds easy.
But what do you do if you want to hold those in version control as well? You
either have to use something like a Git submodule or you have to maintain your
own Fork of oh-my-zsh. I already have a few submodules in my
dotfiles, but it isn’t a very fun thing to manage. Each change
becomes two commits (one for the change, one for the submodule reference), and
it is very easy to forget to push a submodule change while updating the
reference in the main repository.
I had my own fork that I kept my customizations in for a couple years but if I wanted new updates, I would have to merge in the new changes from upstream. It isn’t that bad of a process but it is extra work and I’d argue forks aren’t the best for this.
Where do we go from here then?
oh-my-zsh has done a lot for the community and has helped make zsh popular. This is great but a solution is being developed that addresses these problems.
Let’s take a look at it.
Introduction to Antigen
Antigen cites that it is directly inspired by Vundle, which is a great plugin manager for Vim. Vundle was inspired by Pathogen which was the first plugin manager for Vim. Thus this is the reason Antigen is named after an Immunology term.
Essentially what you do is list plugins in your .zshrc
and it will
automatically download them. It allows you to run various commands such as
updating all the plugins, clean up unused plugins, and more.
The configuration is super simple and it addresses all of the issues with oh-my-zsh. In fact, all of this is mentioned in the Motivation section of the README.
Antigen Features
Antigen has a great set of features as of right now.
Easy Setup & Installation
If you are familiar with Vundle, then Antigen will make complete sense. Here’s what I currently have in my .zshrc for the plugins that I use:
This setup makes it trivial to find new plugins and add them to your setup. Heredocs can be used instead but I find this approach a bit nicer to read.
As an example, before to use z, I had to add a submodule, which
would have to be updated if there were any bug fixes/feature fixes. Then I had
to create a custom/z.zsh
script that would load z.
In my new setup, it has become one line: antigen bundle rupa/z
And retrieving
new updates is just a command away: antigen update
.
Single Dependency
Instead of having to manage an entire fork or submodule, the entirety of Antigen
lives in a file called antigen.zsh
which can be added to
your dotfiles.
In the event that there is a bug fix or feature added, all that is required to
do is to run antigen selfupdate
and then commit the changes. No longer must
must you fetch and merge upstream changes.
Autoloading
Antigen has tries to automatically load various files in a plugin. It has a few mechanisms that it uses to do this. If you are interested in writing a plugin, there is a section on what rules it follows.
Antigen Drawbacks
Antigen isn’t perfect however. There are a few idiosyncrasies that are a bit annoying. Here’s what I think could be improved based off of the current version.
Dependency Errors
Antigen relies on Git and when Git isn’t installed, you are greeted with some pretty errors every single time a shell is opened.
Obviously the fix would be to check if all the required tools are installed before blindly proceeding. It is a simple fix but would make the user experience a bit nicer.
Automatic Downloading is a Mess
In addition to the errors that you get when Git isn’t installed, every time you open a new shell, it will automatically try to download any missing plugins.
This goes with the above point but it would be great to turn this off. I’d argue it should be off by default as well.
Also, if a repository is private, which is what I do to manage sensitive information like IP’s of my servers and other private things, it will try to download it every time a shell is opened up.
This happens on new machines until I get a SSH key in place. The constant errors popping up is quite frustrating.
A more sane alternative is to check if permissions are required and instead of trying to download it every single time, just keep a list of ones that aren’t accessible due to permission. Then the user can download them when they are ready (say after they have setup their GitHub private keys and loaded ssh-agent) instead of the constant errors.
Version Locking
This actually is something missing from Vundle but in some other Vim plugin managers. But there is no way to lock to a specific tag or version (a release in GitHub-lingo).
This would prevent issues where the master is used for development and potential broken changes might slip through.
Conclusion
oh-my-zsh has always had noble intentions, yet it has fallen short as it has grown. I feel that a better, more sustainable solution is required for managing plugins in zsh.
Antigen so far has been a great attempt at that and my chosen tool to remedy these shortcomings of oh-my-zsh. As mentioned, it isn’t without its flaws but that is expected of projects; the base features are there which is far more important.