How do I work on multiple projects simultaneously without losing my mind
Tags: tmux, productivity, automation, bash
Published: 2020-10-27 02:33:43

When you work for a company that has multiple projects running at the same time and your job is to constantly context switch between projects, it becomes nearly impossible to wrap your head around given the project and problem at hand to work on.

Sometimes I am writing K8s ingress configuration for Azure managed Ingress controller where I am required to open up the terminal with Kubectl client configured with the appropriate context, setup VPN connection, open up K8s dashboard to tail logs and sometimes I am writing Dagster pipeline in Python where I am required to set up Redis instance, Celery worker, Rabbitmq, Python’s Virtualenv required, etc etc etc.

I have to sometimes work on 4 to 5 projects in a day and switching between these projects was becoming a pain in my brain. And the worst thing was, it sometimes took me half an hour to switch to project and set up bells and whistles and finally 3 minutes to fix a bug/issue at hand.


![frustation](https://media1.tenor.com/images/3454aa74f6f3b89aba749a28b93932c1/tenor.gif?itemid=7212027)

I knew it was getting out of my hand and I had to do something about it. I knew one open-source tool called [**TMUX**](https://github.com/tmux/tmux) that could potentially solve my issues, but I had not given serious thoughts. I started playing with Tmux once again, it gave me a way to create multiple terminal windows, split a single window into multiple child terminals (also known as panes), switch between multiple terminal windows, and a lot more. It also gave me a way to manage multiple projects simultaneously by allowing me to create multiple tmux sessions. I was super pleased with what it had to offer.

![sample-screenshot](https://miro.medium.com/max/1000/1*wNISmAmDIWRh939jbBEB7A.png)

The above image shows my setup where I have three windows setup for a single project. They are called **function**, **api**, and **database**. I typically name a window based on what they are intended for. If I need to write/debug SQL queries, I would quickly switch to the **database** window and I would switch to **api** if I need to work on the API side of the project. If you look closely, the API window consists of 3 child terminals called panes where I keep Neovim(code editor), Virtualenv activated terminal and Postman process running.

Tmux was a game-changer for me. It gets even better if your primary code editor is Vim. Vim + Tmux simply deserves its Own blog. If I were to put it in one sentence, its nothing but **Match made in heaven ❤**

Okay, now I was able to manage multiple projects using sessions and create multiple terminal windows using Tmux’s windows and panes, you might be wondering if there is anything left to polish. And the answer is **YES** and here are the reasons below:
* The way to create sessions and windows was using its command line program called tmux . For example, to create a new window, you had to run `tmux new-window -c /home/mojo/jojo -n database -t project:1` to split a window into panes, you had to run `tmux split-window -c /home/mojo/jojo...` . You get the idea. It was pretty verbose and imperative.
* I had to remember all those commands every time I restart my laptop or kill the Tmux server.
* When your project is relatively complex, you had to run 30/40 of these commands and hope you didn’t mess up. Imagine doing this for 4 to 5 projects. It quickly gets unmanageable.


Therefore, I wanted something that was more declarative. I wanted something where I could just declare What I wanted instead of How I wanted. I present to you [**mx.sh**](https://github.com/robusgauli/mx.sh) a tool that I wrote for managing Tmux sessions using the declarative configuration file.
{% github https://github.com/RobusGauli/mx.sh %}

Now you are only required to describe your intent such as the number of windows, the number of panes in a window, command(s) to run on each pane, name of a session, etc and [**mx.sh**](https://github.com/robusgauli/mx.sh) will take care of creating a layout that you have described in your configuration file. It will parse your configuration and creates a session with windows, panes, and commands that you have described in your configuration file. Let’s see a sample configuration file below:

{% gist https://gist.github.com/RobusGauli/9106180cee91c24b8fe0937224e96b02.js %} 

The above configuration file manifests the following resources:
* A new session named mojo. This could be the name of the project you are working on.
* Two windows named **w1** and **w2**. In real world, this could be API, database, frontend, etc.
* Window **w1** with two panes whose current working directory is set to `/home/robus` and each pane execute echo command. As you can imagine, your command could `source venv/bin/activate` , `yarn start` , `kubectl config set-context --current --namespace=admin` , etc.
* Window **w2** with three panes.

Hopefully, this should give an idea of how you could extend this configuration file to add windows/panes/command to your likes. If you are wondering, how would the above configuration manifest in an actual Tmux session, below is the screenshot.

![tmux-sample-screenshot](https://miro.medium.com/max/1000/1*VUyHtni9YIhq6T0gz51Zvw.png)

Finally, the way you spin up the new session that is configured to my likes with all the required dependencies is simply

```bash
mx up
```
And if I want to delete the session named mojo

```bash
mx down --session mojo
```
Yup, I am serious. Below is the demo where I am spinning up a project that requires the following components:
* Neovim editor for Lamda functions repository.
* Terminal where I run Serverless commands.
* Neovim editor with python’s flask source code.
* Virtual environment activated terminal session.
* Postman instance.
* Beekeeper instance as GUI SQL client.
* VPN connection.
* SSH into Bastion host.
* Running ‘alias’ command inside in bastion host.
* Access to auth0 dashboard, Jira and Aws console.
* blah blah …

All these setup now requires single command and about 7 seconds to roll. Pretty happy now that I can switch between projects in seconds and let [**mx.sh**](https://github.com/robusgauli/mx.sh) automate everything from starting my code editor to ssh into a remote machine.

![demo-mx](https://miro.medium.com/max/1000/1*RUqaZSzcSF4eCKx6kEkKEg.gif)

I hope this article is useful for those who are suffering similar symptoms of having to spend most of the time getting that initial setup right. If you find my project useful or think you could make improvements, let's do that too.

Cheers!!