January 1, 0001
A Few of my Favorite Things (OSX and terminal efficiency edition)
Here’s a little bit of armchair psychology for you. In the physical world, I thrive in chaos. My office and shop is a haphazard mess of weird gear. My desk is a brightly colored disaster of works-in-progress. But open my terminal window and it’s a picture of military precision. Cleaning my workspace is a chore. But making my terminal more efficient is a delight. What’s it all mean?
I spend 95% of my screen-time in a full-screen terminal. Over the years, I’ve incorporated little tricks that shave seconds off the software development and ops tasks I do every single day. Those seconds add up to high productivity gains.
Fellow nerds who see my console and how fast I operate occasionally ask me to share my configuration (and some have even adopted it!). With this post, I’d like to document some of the tools and techniques I’ve adopted.
The guiding principal is to reduce the physical and cognitive burden of tasks I perform thousands of times every day.
This sometimes means binding a keystoke to a common task. More often it means identifying an action that requires a tiny bit of thought and replacing it with a thoughtless action that can be committed to muscle memory.
Your working memory is a tiny, precious thing. It’s foolish to waste even a single byte.
The Basic Structure
Wherever I ssh, whatever I do, the configuration is exactly the same. I use
tmux to divide my console into two columns. The left column is
vim. The right column is horizontally subdivided into however many stacked terminals as I need. Maybe I have a Docker container or seven spitting out logs in the top terminal and a CLI or two for interacting with that container below.
Unlike some people, I haven’t gone crazy with customizations for
vim configurations. Someone familiar with
vim can use my setup, and I can use theirs without fighting my muscle memory.
The most notable change I’ve made to
tmux is to change the binding for splitting windows. But that’s about all.
I code in
vim. I write prose in
vim. I keep my planner and todo list in text files that I maintain in
I’ve been using
vim for decades now (thanks Dan. I’ve had some time to tweak it a bit. One important bandaid I ripped off was the entirely disable the arrow keys. I’m forced to use many computers as I move from project to project, and no two keyboards have their arrow keys in the same place.
I foolishly bought an Macbook Pro without an escape key as my primary machine, so I’ve been forced to remap caps-lock to escape. That doesn’t work everywhere, so I’m always TOGGLING CAPS accidentally on other peoples’ computers.
I use “dark mode” in vim (and in my terminal overall). I think it helps with eyestrain. Honestly I don’t care to customize my color scheme. The defaults are pretty enough for me.
vim sessions have uptimes measured in months, and I’ll often have dozens of buffers open simultaneously. To switch between them with fuzzy filename matching, I use the CtrlP plugin. I have a variety of other plugins that I use once and awhile, but none that I couldn’t live without.
If you’re a
vim user, it’s worth getting comfortable with the window commands, so you can fluently move text between buffers.
I ssh into a great many computers, and my configuration follows me wherever I go. If I plan to use a computer for more than one minute, I clone my dotfiles into place. My dotfiles are here. To install them quickly I use dotbot
I know that many people who spend a lot of time in a shell environment use
zsh. The passion with which these nerds speak of
zsh makes me think I must be missing a huge opportunity. I personally stick with
bash. Convince me otherwise!
If you’re on a Mac and you’re not using iTerm2, you’re crazy. iTerm2 has a whole universe of possible customizations. I barely scratch the surface.
I’ve re-bound a few keys: cmd-arrow moves me from
tmux pane to pane.
Here are some features of iTerm2 I simply couldn’t live without.
I ssh all over the place, and I like the fact that I see at a glance all the places I’m ssh’ed into. iTerm2 offers split windows, but I’ve relegated that function to
tmux. iTerm2 also has some interesting
tmux integration, but frankly I never found that to be any easier than
tmux (though it is slightly more beautiful).
This is probably the least well-known feature of iTerm2, but for me its a game changer. The basic idea of dynamic profiles is that I can a directory full of JSON files that each designates a separate terminal configuration that can be activated from the menu bar. Crucially, each entry has a unique name (more on this later), and a command that should be run when the terminal is run.
I have an entry for each host I ssh into regularly. Here’s an representative example of a host entry:
(insert complete host entry here) ssh -i <identity_file> user@host -t 'bash -c "tmux a -t main || tmux new -s main"'
This little incantation tells iTerm to:
- ssh to
- run a bash shell that:
- attaches to the
mainor if no such session exists then
- creates and attaches to a session named
- attaches to the
The upshot of this is that when I invoke each dynamic profile, I get a new tabbled terminal containing the
tmux main session. I’m basically resuming whatever I was doing on that host last time I ssh’ed in, or I’m starting a new session that can be resumed later.
tmux session on any host I ssh into is configured just as my local machine is. If I’m working on more than one project on the remote machine, I create a new
tmux window inside the
Before I used this incantation, I would have to worry that I’d left processes running in a detached unnamed session. This trick works incredibly well in concert with the final invaluable iTerm2 feature.
This feature is buried in the iTerm2 documentation, but I can’t live without it. Here’s the magic:
- When in iTerm2, merely press cmd-opt-o to pop open a little floating text input window.
- Start typing the name of a dynamic profile you’ve defined (it will autocomplete).
- If you already have a tab matching that name, hit enter to switch to that tab.
- If you don’t have a tab matching that name, iTerm2 will open a new tab, launch the profile, and switch to it.
If you’ve made a dynamic profile for a host, then you can start working in it without a glance or even a thought. Just hit cmd-opt-o, type the name, and hit enter. Whether you were already connected or not, you’ll find yourself in a tab showing the
tmux main session, exactly how you left it.
Other Mac Customizations
I’ve made a few more tweaks to my Mac that really speed me up every day.
Thor for f-key mapping
Using Command-tab to switch applications is mind-bogglingly inefficient. If you’re writing software, you probably switch applications 1000 times a day (I should count). Every time you do so, you briefly interrupt your concentration to visually example the stack of applications to pick the correct one.
I use a program called Thor to remap F-keys to applications.
F1 opens iTerm2. F2 opens Firefox. F3 opens Unity3d. F4 opens Dash. F5 opens Slack. F6 opens QLab. F7-F9 run some weird compiled Applescripts. F10 opens Toggl for time tracking. F11 opens Fantastical. F12 opens Gmail.
I don’t need to think anymore when switching applications. Muscle memory removes that blip of lost focus.
I keep the touch-bar on my Macbook Pro set to show f-keys at all times. Unfortunately, this is a very poor replacement for actual f-keys and I often hit this bar by mistake and wind up in the wrong application. Did I mention I also miss my escape key?
Moom for window management
I used to run all my applications in full-screen windows. Apple’s full-screen window mode is great with a single display, but it does some pretty weird stuff when you have multiple monitors.
Recently, I’ve begun using Moom to move windows around. I like its keyboard shortcuts and I’m working hard to commit them to muscle memory. I think this is a habit that’ll stick.
On an iPad
This last year I purchased a new iPad Pro 9.7” with a Logitech folding keyboard. I had no idea I would soon be spending upwards of 50% of my working time on it.
I often reach for the iPad before the laptop nowadays because of I can use Blink to ssh into those very same hosts.
tmux does a great job of maintaining my user experience once I’m connected. Mosh is a pretty promising possibility for automatically resuming those ssh sessions, but it seemingly doesn’t play perfectly with tmux (at least in my experience.)
Hopefully this breakdown has been helpful on your own journey to make your computer work more efficiently.