Automate terminal configurations with WezTerm
3 April 2023
9 min read
In the last few months I’ve been trying to automate my terminal configuration for my work/personal projects. Every day having to go through the same process: open a terminal, create tabs and panes, and try to remember which command to run for each project (luckily shell history with fzf helps here!).
So my journey to automate terminal configurations has begun!
Bash & keyboard simulation
I already knew that with xdotool you could simulate keyboard input, so my first attempt was using this tool to simulate my terminal emulator, gnome terminal, shortcuts.
After a few attempts, I managed to get something working (most of the time at least). In the last year I’ve been writing scripts like this, for example this one is used to develop this website:
In order to use this script you need to source it into your shell (I did it inside ~/.bashrc
),
and then after opening a new terminal you can run:
So far so good, right? Yeah…until you accidentaly move your mouse/touchpad, type something on your keyboard or focus another application.
This would interfere with xdotool
commands and your terminal would be left in an inconsistent state.
This worked fine most of the times, but it could also just break randomly without understanding why. Another big issue if you use Linux like me, is that this only works on X11 and not on Wayland, and I’m using both on different laptops.
It was time to look for alternatives.
Terminal multiplexers
Probably someone while reading this said: “Why doesn’t he use a terminal multiplexer?”
Yes you’re right, let’s try zellij and tmux.
zellij
The first impressions were that zellij
is great software!
Great design and usability without even touching the config file (just like tmux…)!
The killer feature for me was its layout system:
Layouts are text files that define an arrangement of zellij panes and tabs.
Let’s try to create the website configuration, but this time I can also use panes that are not available in gnome terminal:
This is the result:
I used zellij for a couple of weeks, and worked pretty nice!
The main disadvantage that made me look for something else, was the command
in the layout file:
- If you wanted to stop it to change to another command the pane would also close (not a deal breaker but inconvenient)
- Integration with direnv (to automatically source environment
variables from a
.envrc
) for commands that needed environment vars to run didn’t work
tmux
I didn’t spend too much time trying tmux unfortunately. I found some promising plugins like tmuxinator, tmux resurrect, teamocil but the overall experience felt worse after trying zellij in terms of configuration and ease of use.
I will save tmux as the last resource if I won’t find anything else.
WezTerm
When you search for the best terminal emulators you always find alacritty, kitty and iTerm2 but very few talks about WezTerm.
WezTerm is a hidden gem! A cross platform GPU-accelerated terminal emulator and multiplexer written in Rust, so it’s blazingly fast. It has a lots of features like tabs, panes and splits, configuration file in lua (with hot reloading) and many more.
The configuration file written in lua opens to a lot of cool things to do, and most importantly it will allow to automate the terminal configuration for my projects!
gui-startup
event
This event is useful for starting a set of programs in a standard configuration to save you the effort of doing it manually each time.
Nice, just what I need 🤞.
Let’s open the wezterm.lua
configuration file and try to use this event:
Now if I open a new terminal, this configuration will be created automatically!
Different projects configurations
Ok, it works the way I wanted. Now let’s face the main issue: What happens if I have to work on another project that is not the website?
One solution is to add an environment variable with the project name you want to start
and use it inside the gui-startup
callback to setup the configuration for that project.
If I open a new terminal, nothing gets created since WZ_PROJECT
is not set.
But if I run this command to start a new terminal, it will be properly created:
Every time I need a new project configuration, I can add a new if statement with the configuration setup.
Refactoring
We’re almost done. What I would like to do before wrapping up is to move all projects configurations out of the main wezterm config file for two reasons:
- As projects configurations increase, readability decreases
wezterm.lua
is committed inside my dotfiles git repository, and I don’t want it to contains all work/personal configurations.
I started by creating a new lua file project.lua
into the same directory as wezterm.lua
(in my case ~/.config/wezterm
).
This lua module will be responsible to find and configure the specified WZ_PROJECT
:
Now we can open wezterm.lua
again and change gui-startup
callback:
Next, we need to create the base_dir
directory (which in my case resolves to ~/.config/wezterm/projects/
) and then we can create a file inside it called website.lua
:
Now open a new terminal and run the same command as before:
We did it 🎉! We decoupled the code that chooses which project to configure and the actual project configuration.
Refactoring: Part II (4 april 2023)
After publishing this article, the WezTerm creator suggested some changes
to further simplify the project.lua
script by avoiding to manually check if the project file exists:
There is a minor change to do for wezterm.lua
as well:
The last change is to how we set the WZ_PROJECT
environment variable because we no longer have to pass the .lua
file extension:
Source code
Here you can find the files we modified/created:
Bonus: wzp
To improve usability I created a bash script, wzp (WezTerm project), that let you choose one of your project and then starts it automatically (using the same command we used before).
Conclusion
It was a long and sometimes tedious journey, but it was fun and I learned a lot! At the end of the day, I found an amazing new terminal emulator, WezTerm, and I could automate projects configurations just like I needed for my workflow.