Managing Zsh plugins the easy way

February 2, 2023


I recently learned that there's a simple way to manage Zsh (and other) plugins with Git, and that I don't need a plugin manager at all. If you look at a Zsh plugin repo (e.g. zsh-autosuggestions), you'll be able to find a .zsh file which is the plugin itself. If we source this file in .zshrc, the plugin is loaded, and that's all there is to it.

Instead of using a plugin manager, you can get these files locally (i.e. clone the plugin repo), then source them in your .zshrc. Update the plugin by pulling the repo.

One approach is using regular Git repos. If you would like to manage plugins as part of a dotfiles repo, another approach is to use submodules.

Using Git repos

# First, we'll need a place to store plugins; I use `~/.zsh_plugins`
mkdir ~/.zsh_plugins

# Then, clone the plugin repo:
cd ~/.zsh_plugins
git clone https://github.com/zsh-users/zsh-autosuggestions.git

# Then, source the plugin in your `.zshrc`:
echo "source ~/.zsh_plugins/zsh-autosuggestions/zsh-autosuggestions.zsh" >> ~/.zshrc

# To use the plugin, re-source your `.zshrc`:
source ~/.zshrc

# To update the plugin, pull from the repo:
cd ~/.zsh_plugins/zsh-autosuggestions
git pull

Using submodules to manage plugins in a dotfiles repo

In short, Git submodules allow you to store Git repositories inside your repository without mixing up the version control of the two. What we'll do is add plugin repos as submodules in our dotfiles repo, then source the plugins from .zshrc. The main difference will be how plugin updates are received.

# First, we'll need a place to store plugins.
# Technically, my submodules are at ~/.dotfiles/home/.zsh_plugins
# Then, that .zsh_plugins directory is symlinked to ~/.zsh_plugins for easier access.
mkdir ~/.dotfiles/home/.zsh_plugins

# Then, we add plugin repos as submodules to our dotfiles repo:
cd ~/.dotfiles/home/.zsh_plugins
git submodule add https://github.com/zsh-users/zsh-autosuggestions.git

# The plugin repo now exists in this directory.
# The plugin will be at:
# ~/.dotfiles/home/.zsh_plugins/zsh-autosuggestions/zsh-autosuggestions.zsh

At this point, if you want to symlink ~/.zsh_plugins to the .zsh_plugins directory in your dotfiles repo, you can do that.

ln -s ~/.dotfiles/home/.zsh_plugins ~/.zsh_plugins

Then, source the plugin from .zshrc:

echo "source ~/.zsh_plugins/zsh-autosuggestions/zsh-autosuggestions.zsh" >> ~/.zshrc

# To use the plugin, re-source your `.zshrc`:
source ~/.zshrc

Updating submodules manually

# To update all submodules of your dotfiles repo,
# run the following from anywhere (except a submodule)
# inside your dotfiles repo
git submodule update --remote

# To update a specific submodule,specify which submodule to update
# after --remote, e.g.
git submodule update --remote ~/.dotfiles/home/.zsh_plugins/zsh-autosuggestions
# or
cd ~/.dotfiles/home/.zsh_plugins
git submodule update --remote zsh-autosuggestions

Updating submodules with Dependabot

Dependabot supports monitoring submodules for updates:

version: 2
updates:
	- package-ecosystem: "gitsubmodule"
		directory: "/"
		schedule:
			interval: "monthly"