Making tmux work for you
When it comes to my developer toolset, I like solutions that I can easily understand and tweak. I guess I’m not the only one. I believe that for a lot of people one of the (many) reasons to join the Ruby bandwagon was that you could do virtually everything without a big, fat IDE, that I never know what it’s doing and how. Just your editor and console. First class citizens.
And I still like this kind of workflows. But, let’s be honest, sometimes there are moments, that you wish your tools did a little better when it comes to helping you with tedious tasks.
You can often find an editor plugin that does what you need. And it’s fine. But sometimes you’re like: do I really need to pull another plugin to do this simple thing?. After all, we’re programmers. We can program basically anything, why not our developer environments.
It seems to me, that often what we need are just the proper building blocks.
tmux is one of such building blocks, that can really help you a lot when it comes to automating your developer workflows. Generally one could say it’s a
screen on steroids. It let’s you manage terminal sessions and interact with them programmatically.
On Mac OS you can install it with
brew install tmux.
It’s a powerful and versatile tool - a lot of people us it for a lot of different things. I’m neither a heavy, nor a longtime tmux user, but let me present a couple problems where it paid off for me. I’m not encouraging you to adopt “full tmux workflow”, whathever that means, but maybe it’ll show how you can easily solve a specific problem yourself.
Solution 1 - launching gazzillion servers locally
Sometimes you work on a project with one rails server and probably a background worker. Not a big deal to launch when you start your work in the morning. But what when you have 10 microservices? You don’t want to do it by hand.
Of course, there are so many tools that can help you with that, pow, puma-dev, docker, whatever. But you don’t always wanna learn and employ a new tool to do a dead simple thing like launching a server. You wanna keep it simple, and not spend a day on configuring a specific solution.
How did tmux help me with that? I simply wanted something that will just “prepare” terminal windows for me, so that I can later interact with them in a “typical” way, like
^C to kill the process, then press up and enter to start it again, rather that running the processes in the background, etc. I often want to tweak my workflow step by step, rather than by revolution.
tmux has this nice command “send-keys”. What does it do? Yup, it sends a particular key sequence to the terminal session. As simple as that. Let’s have a look at this sample tmux invocation:
tmux \ new-session -s your_session_name \; \ send-keys -t :0 "cd ~/app_1" Enter "bundle exec rails s -p 5000" Enter \; \ new-window \; \ send-keys -t :1 "cd ~/app_2" Enter "bundle exec rails s -p 6000" Enter \; \ new-window \; \ send-keys -t :2 "cd ~/app_3" Enter "bundle exec rails s -p 7000" Enter
tmux binary invocation let’s you specify multiple tmux-commands:
new-sessionstarts a new session with given name, that you can later identify it with in
new-windowopens another window within a session. They’re identified with numbers like this:
send-keys- tmux tries to make it easy for you and guess whether you meant a key or literal sequence:
Enterdoes what you’d (not) expect
Once you launch your script, you can:
ctrl+bfollowed by window number to switch window
dto detach from the session - now everything is in the background (
ctrl+bprefixes all tmux hotkeys; people often sometimes it to
tmux ato attach to it again. Add
-t your_session_nameif you have more of them
tmux kill-session -t your_session_nameto quit everything. Same as exiting every terminal window one by one.
tmux lsto see all the sessions
Tweaking the config
You’ll find your tmux config in
- remap alt+left & alt+right to easily switch to the left/right window:
bind -n M-Left select-window -p bind -n M-Right select-window -n
- start window numbers from 1 to match keyboard ordering
set -g base-index 1 set-window-option -g pane-base-index 1
- give your windows specific names to show up on the status bar: just do this
new-window -n app_1_bg_workerin the launching snippet
- start the session initially detached:
- put it all in a handy script in you PATH - so that you can later just type
myproject start|quitfrom any directory
- if you use iterm on Mac OS, you can enable tmux integration and attach to the session like this:
tmux -CC a- this way your tmux session will appear as a normal iterm session and you can use all your hotkeys as you normally do
Working with multiple repos?
By the way, if you sometimes happen to work with multiple repos, you might wanna have a look at this shell-one-liner: multigit - it lets you run (git) commands on all “sibling” repos.
Solution 2 - spinning off builds/tests in a terminal session
…to come in another blogpost - but the building blocks are the same, no additional magic needed :)