5 min read

A Few of My Favorite Developer Tools

tldr is secretly the reason I’m writing about any of this. It provides example-based documentation for a ton of Unix commands. So if I run tldr sed, I get (among other examples):
A Few of My Favorite Developer Tools

Tldr: run brew install tldr

I picked up a habit at Pivotal of managing my workstation with a script. Any machine I get access to, really-- working on a container platform for a few years trained me that bits on a hard drive are so many sand castles by the ocean, never more than moments away from the next wave. Actual physical pieces of metal a little less so, maybe, but being able to bring up a copy of my system on command comes in handy. I get to nope out of a lot of yak shaving, because if things get real weird I can re-image the machine and start over.

Now that I’m no longer relying on a team workstation, I’ve started working on my own setup script. It’s pretty simple at the moment, since I only add things as I need them, but that means that everything that’s in it is one of my absolute favorite tools, so I thought I’d give you a run-down of what’s in there and why.

(Note that I haven’t tested this on an actually clean Mac OS X build in a few months, so while you’re welcome to run this script yourself, you will probably run into some kind of bug. If you do, I’d love it if you filed an issue on the repository. You will also need to install the Xcode command line tools.)

The repository has three pieces: a script that I run just once, a script that I run regularly, and the Brewfile, which contains most of the applications that I install.

The bootstrap script installs Brew itself, and oh-my-zsh. I only ever want to run these commands once on a machine right now for a few reasons.

One is, they’re slow. They’re both shell invocations of scripts downloaded with curl, and they don’t check in any way to see that the work has been done already before they execute. The brew install just goes ahead and runs anyway, but the zsh installer actually errors out now, with a helpful message about your options to get it to run anyway. I could fix this by adding a guard clause where I check for the presence of an artifact they’re going to create before I run the installer, but I’d have to go and figure out what to check for, and it would make the script a little more arcane. “If” statements look weird in Bash, and their presence is often a sign that I should switch to a different language, so if I can avoid them I will.

They’re also, well, running scripts that they download themselves from the internet. I don’t want to do this very often. I especially don’t want to be in the habit of running a script multiple times a day that asks for my password, as the brew installer does.

Happily, it works just fine to pull these things out into their own run-once script, because brew and zsh can handle their own updating. So I get to pull one of my favorite software engineering moves, and avoid a hard problem rather than solving it.

The run-all-the-time script calls Brew bundle, installs a Ruby, and sets up a couple of oh-my-zsh plugins.

I’m using oh-my-zsh mostly out of habit— it’s probably overkill, since I’m not doing anything especially interesting to my shell. It is quite nice for multi-user workstations where you end up with big piles of aliases to manage.

For Ruby management, I use chruby and ruby-install. This is a very mild preference — I’ll happily use rbenv if that’s what the team is already using — but “rewrite the $PATH when I change versions” matches my mental model of what ought to be happening when I change Ruby versions, so it’s easy for me to debug when something doesn’t behave quite how I expect. Shims still confuse me.

jq is a great little Swiss Army knife for messing with structured data. I use jq . all the time to just to make JSON easier to read. I do have to look up the syntax and fiddle around a little bit any time I do anything more complicated, though.

tldr is secretly the reason I’m writing about any of this. It provides example-based documentation for a ton of Unix commands. So if I run tldr sed, I get (among other examples):

- Replace the first occurrence of a string in a file, and print the result:
    sed 's/find/replace/' filename

- Replace all occurrences of an extended regular expression in a file:
    sed -E 's/regex/replace/g' filename

- Replace all occurrences of a string [i]n a file, overwriting the file (i.e. in-place):
    sed -i '' 's/find/replace/g' filename

Super super handy, especially for tools that I only use occasionally, and I can remember in general what they do but not the exact runes to invoke the thing I always want to do. Install it, like, yesterday.

ag is probably not the best searcher out there these days but it’s the one I’m used to. I think of it as “grep, but fast, and with defaults for searching in directories rather than single files.” By default it prints the filename in bold and includes the line numbers in the file for any hits. I also use ag -l a lot.

Finally, z means never having to remember my local directory structure. Very handy on teams deeply committed to whatever the opposite of a mono-repo is. (Multi-repo?) It requires a modification to your shell configuration to work, which in my case is provided by the zsh plugin.

If you like the headline image, go check out Egor Kamelev on Pexels.

This post is for subscribers only