Will's avatar

⬅️ See more posts

Tmuxinator: simple terminal workspaces for your projects

18 June 2021 (5 minute read)

🔮 This post is also available via Gemini.

100daystooffload technology

💯 100 Days to Offload

This article is one of a series of posts I have written for the 100 Days to Offload challenge. Disclaimer: The challenge focuses on writing frequency rather than quality, and so posts may not always be fully planned out!

View other posts in this series.

Living without workspaces

IDEs and richly-featured text editors - such as VS Code and Sublime Text - support many great features. One of these is the notion of projects or workspaces.

Such workspaces let you save your project’s development configuration to disk - things like the project directory, open files, editor layout, integrated terminal commands, and more. Often, each project can have its own workspace, too.

If you use workspaces then you don’t need to go through the tedious process of setting everything back up again each time you switch project, re-open your editor, or reboot your computer.

However, if, like me, you use the terminal as a primary development environment, things don’t work quite so nicely out of the box. For example, I use tmux as my primary development environment, and make use of multiple windows and panes for things like Vim, source control, logs, and running commands.

At any given time, I might have a handful of tmux sessions running (one for each project). A single small session project might consist of a web API service and a separate front-end - each comprising Vim editor panes, and a mix of other things. Context switching is super easy, as I can just detach from a session, and then re-attach to another one that tmux has kept running for me in the background.

However, the pain point comes when rebooting. Once the tmux server process terminates, all of the running sessions are lost. This means setting each session up again individually each time you want to begin working on a different project after rebooting.

It certainly feels like a blocker to performing system upgrades that require reboots, and is also extra friction that may prevent one from working on specific projects if the set-up is too painstaking. Both of these are clearly not good.

However, there is a solution: tmuxinator.

Tmuxinator

Tmuxinator is a program that partly aims to try and fix the workspace problem for tmux-based workflows, and my life is so much easier because of it.

The program does not interfere with the tmux server directly, and neither does it maintain individual explicit tmux session data - tmux sessions are still lost after reboot.

However, what it does do is make workspace session management so much easier by storing your project window and pane layout in a simple YAML file on disk.

For example, a simple API and separate web front-end project (as mentioned above) could be described as the following tmuxinator project:

name: cool-project
root: ~/project/my-cool-web-project

windows:
  - api:
      root: ~/project/my-cool-web-project/api
      layout: main-vertical
      panes:
        - vim
        - app:
          - source .venv/bin/activate
          - source .envfile
          - flask run
        - zsh
  - frontend:
      root: ~/project/my-cool-web-project/web
      layout: main-vertical
      panes:
        - vim
        - yarn start
        - zsh

This project represents two tmux windows, each with three panes: an editor, a server (or watcher), and an empty shell pane that can be used for issuing commands (like git). The inbuilt main-vertical layout automatically provides a nice, big Vim window (in these cases) for editing, and then a vertically-split extra pair of panes.

Each window has a separate root directory, and the project as a whole has its own root directory too, to provide better automatic working directories in case new windows are later created when inside the session. Each session and window also gets its own name (e.g. api and frontend above) to make identification easier later on.

If this file is stored in ~/.config/tmuxinator/cool-project.yml, one can simply run tmuxinator start cool-project to get started. If the project is already running it will attach you to it as-is. If the project is not currently up and running, tmuxinator will go ahead and create all your windows and panes, run the commands you specify, and connect you to the new session.

Once inside the session, it’s just controlled by plain old tmux. To detach from the session, just use the usual tmux sequence (by default ctrl-B-D). You can then connect back to the same session or another one.

Creating more project configurations

Tmuxinator comes with lots of other commands to make set-up easier. For example, running tmuxinator new <project name> will open up your editor on a template YAML file for you to edit and then save.

If you have lots of similar types of projects with the same layouts then the copy command is useful for duplicating projects as a convenient start-point: tmuxinator cp <existing> <new>. You can also list and delete projects in a similar way: tmuxinator ls and tmuxinator rm <project name>.

Definitely take a look through the documentation to learn more about these and other commands.

Installing tmuxinator

Many distributions include tmuxinator in their repos. On macOS it’s a simple brew install tmuxinator.

Take a look at the installation instructions for more information.

Backing-up and syncing projects

Being able to recover tmux sessions is great, but what if you want to sync projects between devices, or back them up?

There are various approaches for this. I store my configuration files in my personal Nextcloud, which means I can hydrate any new devices with a simple link:

ln -s ~/Nextcloud/dotfiles/.config/tmuxinator ~/.config/tmuxinator

That way, if I use tmuxinator new to create a new project configuration it will automatically get synced to my Nextcloud. This approach also works if you use software like Syncthing.

If you work in a team and want to share your setup through version control, you could also commit the project-specific YAML file to your repo. The tmuxinator start command will look in ./.tmuxinator.yml before anywhere else, and so this offers a nice way to get your whole team using a consistent setup. However, in my experience the workspace setup can be quite a personal thing!

If you have any other thoughts for maintaining terminal-based workspace sessions, then I’d love to hear them. Please let me know.

✉️ You can reply to this post via email.

📲 Subscribe to updates

If you would like to read more posts like this, then you can subscribe via RSS.