I write software sometimes. Usually when I have a problem.
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.
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.
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.
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.
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.
2019, Elixir
ConfigSmuggler implements a plaintext, environment-variable-friendly
serialization language for Erlang/Elixir style configs. Super useful when
interfacing with external config stores.
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.
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.
2018, Rust
A JSON transformer. Pretty prints and minimizes with configurable formatting.
2017, Elixir
StripJS removes executable JavaScript from HTML and CSS documents.
A useful tool in a larger defense-in-depth XSS prevention strategy.
2016, Elixir
Simplifies the creation of Elixir structs by translating between atoms
and strings, and between camel case and snake case.
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.
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.
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.
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.
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.
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.
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
/dev/null/nethack is long extinct, but its spirit lives on in
The November Nethack Tournament
conducted by Hardfought.org.
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.
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.
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.
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.
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.
Tapper
Moloch Bot
Tuilet
PoisonPill
Imagewriter
ConfigSmuggler
Mojito
Freedom Formatter
JsonXf
StripJS
ExConstructor
FuzzyURL
Canobie
HyperResource
Flac2Lame
Brick
DSt
Clan EIT Elite Scoreboard
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.
FBay
Cretin
Schlitz BBS
DCI
Choad