Software

I write software sometimes. Usually when I have a problem.

Tapper

2026, Rust

Tapper is a TUI audio player for macOS and Linux. The main goal is to play audio files that live on high-latency network drives (like, say, the mp3 collection on my ancient RAID) without glitching. In active development.

Moloch Bot

2024, JS

Moloch Bot was written in November 2024. It posts quotes from part 2 of Allen Ginsberg's Howl using a Mastodon account. I was angry.

Tuilet

2024, Rust

Tuilet is a TUI wrapper around the venerable text-art generator Toilet, which evolved from the even more venerable Figlet. Experiment with fonts and colors like never before! It was a good excuse to learn the delightful Ratatui library in the name of IRC shitposting.

PoisonPill

2020, Elixir

Runs an external program to determine whether your BEAM VM lives or dies. Useful when your code is buggy and you don't know why, but replacing servers helps under certain conditions. It's a messy world.

Imagewriter

2020, Ruby

Quite possibly the best printer driver for the Imagewriter and ImageWriter II ever released. Produces high-quality output on even janky old printers with memory issues. Dovetailing is the trick.

ConfigSmuggler

2019, Elixir

ConfigSmuggler implements a plaintext, environment-variable-friendly serialization language for Erlang/Elixir style configs. Super useful when interfacing with external config stores.

Mojito

2018, Elixir

Mojito is an HTTP client library built on the low-level Mint client. Released several hours after Mint -- my first 0-day!

It was born the day after the first EMPEX LA conference, where I was whining to ericmj and whatyouhide about HTTP client performance on the Erlang VM, which was pretty crappy at the time. They smiled like they knew something I didn't (which is unquestionably true). I then buttonholed them more and more uncomfortably until they gave up the URL to the in-progress repo ("XHTTP"). I wrote the first version of what would become Mojito ("XClient") on the airplane home, but it was not ready for production so it just sat there.

About a year later, I saw a release announcement for Mint. It took me about an hour to take my old code and make it work with the updated version of theirs, and I released it the same day.

We used it at work for a while until someone wrote a faster client called Finch.

I wrote most of this library and it had a lot of users. I'm proud of the API it presents. Someone at work later surprise-archived the project and Github repo at least partially to hurt my feelings.

Freedom Formatter

2018, Elixir

It was 2018 and the industry was still getting used to automatic code formatters. The Elixir project introduced one (this is fine) but it deleted trailing commas on lists (this is utterly deranged). So I forked the code and added support for trailing commas, and opened a PR to Elixir. José Valim is a brilliant man of nearly impeccable taste, but boy did he whiff this one (very politely, I should add).

I released it in jest as a standalone project, which was a pain cause I maintained it as a patch against the stock Elixir sources, and the formatting code was both gnarly and frequently-changing. Then an angel in the form of marcandre stepped in as a new maintainer.

JsonXf

2018, Rust

A JSON transformer. Pretty prints and minimizes with configurable formatting.

StripJS

2017, Elixir

StripJS removes executable JavaScript from HTML and CSS documents. A useful tool in a larger defense-in-depth XSS prevention strategy.

ExConstructor

2016, Elixir

Simplifies the creation of Elixir structs by translating between atoms and strings, and between camel case and snake case.

FuzzyURL

2015, Ruby + Elixir + JS

A tiny DSL for fuzzy/glob-matching of URLs. I wrote three implementations that work the same. I always wanted to write something comparing the API of each. Never got around to it.

Canobie

2015, Elixir

At work in 2014, I came across our CEO and our (awesome) HR lady having a suspiciously heated discussion at lunchtime. In short, they wanted to plan a company outing, HR wanted it to be fun, and the CEO wanted it to be cheap. So I pitched them the idea of a scavenger hunt around Boston. It went great, and I went completely nuts tabulating all the scores by hand.

The next year, we had enough money due to Series C Disease that we could all go to an amusement park, Canobie Lake Park. The HR lady came to me with the good news that the park already had a scavenger hunt written up that we could use. I looked at it, and it was the most inane and bland hunt I could have imagined. Now, I grew up near Canobie Lake Park, and it was far too dear to my heart to let my coworkers experience this drivel.

I came up with a scavenger hunt that showcased the qualities that make Canobie Lake Park what it is. You got points for riding rides, eating food, eating food then riding rides, staying in the beer tent the whole time (hi, sales team!). You got points for seeing preteens making out, or a puddle of puke on the ground, or a parent ripping butts in the smoking gazebo while their kid is on a ride.

For scoring, I wanted an app that let members of a team check an item on a checklist, and for that item to be checked for everyone on the team. Seemed like a good case for websockets, which to that point I had only ever wrangled in Scala, which was awful. I had heard about this new language called Elixir, and the web framework Phoenix, and figured this would be a good time to try it.

The websocket code took around 20 minutes to write and test. I was impressed. Later that year, I would go on to choose Elixir as the backend language at my next job, a decision I never regretted.

HyperResource

2013, Ruby

In the early 2010's, hypermedia was in the air. Minimal formats like HAL made generating hypermedia APIs easier than ever, but there was limited client support. I wanted an API client that was designed to be completely driven by hypermedia.

Using the deprecated but wonderful ActiveResource library as inspiration, I spent the next year and a half of mornings, evenings, and weekends writing a "self-inflating", hypermedia-driven HTTP client called HyperResource. In a way that only a language like Ruby could pull off, you could more or less gesture at what you wanted to do, and the client would do what it needed to do to make it happen.

It had admirers but few users. I wrote a paper on it and got accepted to the WWW 2014 conference in Seoul! Well, accepted to the WS-REST subgroup anyhow. I got to present my ideas to a roomful of very smart people, most of whom were from academia. I also got to visit Asia for the first time and eat Korean food until my eyes rolled back. I ate kimchi with every single meal except the end-of-conference banquet, which was inexplicably European food. Korean Air made it right, though; everyone on the plane home received a pouch of kimchi, almost like airline peanuts 30 years ago.

As for hypermedia APIs, there isn't much more to say. Facebook released GraphQL which has a very different worldview, and within a few marketing-heavy years, it paved over everything else -- not unlike React would a year or two later. The field has not recovered.

Flac2Lame

2012, Ruby

Flac2Lame takes properly-tagged FLAC audio files and encodes and tags them using the Lame MP3 encoder. I have used this more than a few times over the years.

Brick

2011, Ruby

Brick is a scoreboard for an esoteric dice game played around MIT. It's like Cosmic Wimpout but different. For over fifteen years, Brick has served as the system of record, with scores dating from the 1990s to present.

DSt

2010, JS

HTML 5 was new and exciting. So was the DOM Storage API. It makes it easy to save form state to and from DOM Storage. I wrote this as a proof-of-concept for a contract I didn't get.

Clan EIT Elite Scoreboard

2008, Perl

There's this game called NetHack, and back in the 200\d's there was an annual tournament called /dev/null/nethack. The tournament was a lot of fun, but the computing resources of the host server were modest. There was a lot of fun to be had analyzing odd statistics, but the organizer generally had their hands full just putting things together and keeping them running.

I am a member of Clan EIT, the world's first and most elite NetHack clan. I built a scoreboard partially so people could see the standings without a 90 second page load. (Amusinglly, TTFB was quick because the code began something like print "Content-type: text/html\n\n";.) But I also built it to answer the hard questions. Who winning the "Killed by a shopkeeper" trophy? Who got killed the most times while they were hallucinating. Who has the lowest points-per-game? This is what keeps people up at night.

/dev/null/nethack is long extinct, but its spirit lives on in The November Nethack Tournament conducted by Hardfought.org.

FBay

2008, Ruby

In 2005, a good friend and former housemate named Frostbyte died. I can't capture the whole essence of Frostbyte, his death, or Warehouse 23 here. Suffice it to say we lived in 7000 square feet, and there was a *lot* of tech gear to deal with. It got put into storage for an eventual auction.

In 2008, eight days before the auction, I got a call asking if I could write some software to handle it. The goal was a multi-unit ascending auction comprising hundreds of unique items, sold separately or in lots for the lowest winning bid. There was some Perl package that almost did about 1/3 of what we needed, but I didn't feel good about it. So I said I'd write something from scratch.

My friends were nervous. I was nervous too. I'd been writing Perl web apps for a couple of years, but was fairly certain I would not be able to complete one in time. But I'd heard very good things about the language Ruby and its web framework Rails. I learned enough Ruby in about 15 minutes, and began.

Thanks to Rails 1.x's view scaffolding, the server was happy to shit out bland-looking CRUD views all day, and I could focus on the data model, the part that should be the hard part. Eight days passed and I had a working system. I ran it off my iBook G3 and it was hot enough to cook an egg.

This project ended up getting me my first startup job, doing Rails. That ended up being pretty important to my career.

Cretin

2007, Perl

If you scroll down to the bottom of this list, you'll see Choad. It ripped CDs to MP3 and pulled the artist, title, album, etc. information from CDDB. It produced properly-tagged files with customizable naming.

Choad was good, and I ran it on all my CDs. But the times being what they were (not to mention encoders), I skimped on sound quality, choosing a constant bitrate of 160 kbps in order to save on disk space.

Seven years later, I bought my first good pair of headphones, Grado SR80's. Never before was it so clear that I had messed up by choosing a low bitrate. I set out to rip my CD collection again, but one last time.

The new tool would encode to a lossless format, FLAC, in addition to MP3. And it would use every CPU and CD-ROM drive in the house to do it. This way, I could listen to either FLAC or MP3 depending on the bandwidth available, but I always had the lossless copy so I'd never have to touch the discs again.

SourceForge was where most people put their code. They declined to host a project named "Choad", so I christened the new tool Cretin: the CD Ripper, Encoder, and Tagger with an Inoffensive Name.

I'm glad I built it, but it was pretty much a single-use tool for me.

Schlitz BBS

2006, Perl

The local bicycle chopper gang I used to ride with had an HTML messageboard. And I really mean that: the system of record was a directory of HTML pages, which the cgi-bin scripts would edit in-place when new comments were posted. It looked ancient and was not terribly reliable. I thought I could make it faster and more reliable while retaining some key features like cross-site scripting attacks (no, really, we wanted this) and Web 0.9 aesthetics. I named it after the beer we used to drink on rides.

It's written in old-school Perl web style, where you'd write scripts that spit raw HTTP responses over stdout. All SQL is handwritten, and I was not very good at that yet. But as of summer 2026, Schlitz BBS has been in production for about 19 years, so it works well enough.

DCI

2006, Perl

I was in school for electrical engineering and in love with my HP 32S-II calculator. I was very fast at using it for lots of EE problems. But there were times when I was at a computer, and the calculator was not in front of me. I liked /usr/bin/dc, an RPN calculator that's part of Unix, but it didn't do trigonometry.

I wrote a dc replacement in Perl, adding things like trig and polar/rectangular coordinate translation. I didn't know how to write a parser, but it's pretty easy to break apart RPN with a regex. Perl was big on regexes, and I was big on Perl, so I did it that way. I called it DCI because it's DC Improved. It's also DC++ if you are using Roman numerals.

It has a couple of bugs I never had to fix and I am always thinking about building a new version, building it "right". But I use this program once a week. It's my oldest code I still touch.

Choad

2000, Perl

The one that started it all. I had CDs and I wanted to rip them to MP3. This was easy enough to handle; CDParanoia would spit out lovely WAV files, and I think I was using BladeEnc to encode to MP3. But adding the tags and naming the files was a pain. CDDB was a free service where people could look up track info and submit it if it were not there. All someone needed to do was glue it all together.

I don't remember why I named it Choad, other than that it's vulgar.

I used it, it did what it was supposed to, and then I didn't need to use it much. A few months later, iTunes came out and it did everything I needed, and over the next few years I used Choad less and less until rewriting it into Cretin in 2006.

This was the first project I released as free software, and the first to give me the mind-blowing experience of someone else making my code do more stuff and fixing its bugs, for free. It was actually through one of those patches (literally, inputs to the Patch tool) that I recovered my source code years later.

← Back