Tmux plugin development with a local repo

| 2 min read

This weekend I wrote a simple Tmux plugin, tmux-focus-status, mostly to learn how to do it, but also to modularise my Tmux configuration (perhaps organising chunks of configuration into plugins is a little extreme, ah well).

The way you add a plugin to your Tmux configuration requires you to specify a remote git repository, such as on GitHub or BitBucket. This would mean I'd have to push my fledgling plugin to GitHub to test it out in the context of Tmux itself, but I wanted to keep everything local while I developed it. So I used a bare repository on the local filesystem. Here's how.

The plugins are managed by Tmux Plugin Manager (TPM) and there's a great document on how to create a plugin here: How to create Tmux plugins.

While the plugin itself is essentially a script that uses tmux commands, including the plugin into your configuration and testing the installation and use in a real session means that you have to have the plugin code in a remote repository. The examples in the main TPM README imply this:

set -g @plugin 'github_username/plugin_name'
set -g @plugin 'github_username/plugin_name#branch'
set -g @plugin 'git@github.com:user/plugin'
set -g @plugin 'git@bitbucket.com:user/plugin'

Nothing wrong with that at all, but I wanted to get the plugin right before pushing it anywhere like GitHub. So I remembered that you can initialise a repository with the --bare option (see the "Bare Repositories" section in this document), and this will effectively create a shared repository that can be used as a remote.

I was developing the plugin in a directory called:

~/work/scratch/tmux-focus-status/

and had run git init in there, and committed my work.

I then created a bare repository with the --bare option, like this:

cd ~/work/remotes/
git init --bare tmux-focus-status.git

The convention is to add the .git ending to repositories initialised like this.

Then I set up this location as a remote in my plugin directory:

cd ~/work/scratch/tmux-focus-status/
git remote add local ~/work/remotes/tmux-focus-status.git

Calling the remote local might seem a little counter-intuitive, but it works for my brain.

Having pushed the work to that remote:

cd ~/work/scratch/tmux-focus-status/
git push local main

I could then reference that local filesystem remote in my Tmux configuration, alongside my other plugin lines, like this:

set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-sensible'
set -g @plugin 'christoomey/vim-tmux-navigator'
set -g @plugin '/root/work/remotes/tmux-focus-status.git'

I was doing this in a temporary dev container hence the /root home directory.

And on invoking the TPM "install" function (with <prefix> I, see the keybindings info), the plugin was successfully installed:

Already installed "tpm"
Already installed "tmux-sensible"
Already installed "vim-tmux-navigator"
Installing "tmux-focus-status"
"tmux-focus-status" download success

TMUX environment reloaded.

Done, press ESCAPE to continue.

Excellent!

Using local filesystem based remotes is also nicely summarised in How to use local filesystem remotes with git which I found helpful.

Note: You can also just clone the repo from the directory it's in, but it feels nicer and more organised to bridge this via a "real" git remote connection. Thanks to my son Joseph for pointing this out :-)