Programming
Here's various open-source software that I've written over the years, along with assorted information that may be of interest to other programmers.
Projects
Most software that I've written and open-sourced is available at github.com/derat. Here's an incomplete list in no particular order:
nup is the system that I use to organize and play music that I've purchased. It consists of a Google App Engine app written in the Go programming language and includes a web interface for searching for and streaming songs. I've spent a lot of time working on it but I'm not sure whether it will be useful for anyone but me (hmm, that actually describes a lot of my projects…). I pulled some code for processing audio files out into a separate mpeg library.


nup-android is an Android client for nup written in Kotlin. Compared to the web client, its focus is less on organizing music and more on playing it (e.g. it caches songs for offline playback).




duoleavemealone is a Chrome extension that makes the Duolingo language-learning site a bit easier to use by automatically clicking through pointless screens. It's installable from the Chrome Web Store.
xsettingsd is a C++ daemon that
implements the XSETTINGS specification.
It's intended to be small, fast, and minimally dependent on other libraries. It can serve as an alternative
to gnome-settings-daemon
for users who aren't using the GNOME desktop environment but who still
run GTK+ applications and want to configure things like themes, font antialiasing/hinting, and UI sound
effects.
cloud-build-watcher is a Go
Cloud Function that sends email notifications and generates
badge images like
soundalike is a command-line program that
tries to find similar audio files by comparing acoustic fingerprints. Its main focus is identifying
duplicate songs in music collections. It uses the fpcalc
utility from the
Chromaprint library to generate fingerprints.
rendmail is a command-line program that can be executed by a message delivery agent like procmail or fdm to remove binary attachments from MIME email messages before they're delivered locally. I wrote it so I could use it when doing local backups of email stored on a webmail service.
yambs (Yet Another MusicBrainz Seeder) is a command-line program that seeds edits to the MusicBrainz database from text input (e.g. CSV or TSV) files or Bandcamp pages. I also made a web interface that can be accessed at yambs.erat.org.

check-page-speed is a command-line program that calls Google's PageSpeed Insights API to generate Lighthouse reports about web pages' performance, accessibility, adherence to best practices, and so on. It can be run periodically via cron to summarize the results and send them via email.
aread is a Go server for saving web pages to read later. It uses Mercury Parser to simplify pages and can send them to Amazon Kindle e-readers.


ascenso is a web app for recording participants' scores in endurance rock-climbing competitions (and it's been used successfully a few times!).


mpticks is a web app for viewing ticks (i.e. your climbing history) from Mountain Project. It's still running here, but Mountain Project got sold in late 2020 and the new owners shut down the API.


intransigence is a static website generator that I wrote for this site. I also created Go libraries named htmlpretty and validate for pretty-printing and validating the pages.
nitter-rss-proxy is a Go HTTP proxy that makes it easier to read RSS feeds that Nitter generates from Twitter timelines.
watchbrainz is a Ruby script that can be used to monitor the MusicBrainz database for new music releases by artists that you like.
home is a system for collecting environment data (e.g. temperature, relative humidity, network connectivity, line power status) and reporting it to a Google App Engine server, where it can be graphed or used for alerting.

advent-of-code contains my Go solutions for the Advent of Code programming challenges that are released every December. (If you're a programmer with a bit of free time, you should consider trying Advent of Code!)

mbstats is a command-line program I wrote to process MusicBrainz database dumps and generate statistics about edits. You can read more in this forum thread.
bind-to-tinydns is a little C program that parses zone files used by the BIND DNS server and spits out their content in the native format of the tinydns component of Dan Bernstein's djbdns DNS server. It should be pretty fast (it does a single pass of each entry and doesn't dynamically allocate any memory) and it makes more of an effort to mimic BIND's behavior than other programs and libraries that I've seen that parse zone files. Be advised that I wrote it a long time ago at a previous job and can't vouch for the quality of the code — there's a frightening amount of premature optimization around string manipulation.
craigsnipe is a Python script that scrapes Craigslist RSS feeds for items matching certain criteria and sends them as email. It's pretty rough around the edges (SQL queries are required to configure it) and I haven't used it in many years.
Converting my website to AMP (Accelerated Mobile Pages)
I wrote a long thing about how I generated an AMP version of this website.
Supporting dark mode in web pages
I wrote about adding support for dark and light themes to web pages.
Generating thumbnail placeholder images for web pages
If you're including a bunch of images in a web page, thumbnail placeholder images can help hide the loading time.
NearlyFreeSpeech.NET tips
I documented some useful tips if you're using NearlyFreeSpeech.NET to host a website.
Running Node.js and npm JavaScript code as an unprivileged user
I finally grew uncomfortable enough about running untrusted JavaScript that I figured out how to run it using a less-privileged account.
Testing procmail and fdm configurations for local email delivery
I wrote some advice about how to test that the configuration for a Message Delivery Agent like procmail or fdm works the way you expect.
Generating RSS feeds for Feedly
I wrote down miscellaneous advice about generating RSS/ATOM/JSON feeds for the Feedly feed reader.
Shell recipes
A collection of useful bash and zsh configuration snippets.
Debian on an ASUS Chromebox
I documented my experience getting Debian GNU/Linux to run on an 2014-era ASUS Chromebox.
Software rants
Behavior of Go print functions
I am confused by the behavior of Go's Print and Println functions across different packages.
Older projects
Here's some older code that's unavailable on GitHub or that I'm not actively maintaining anymore.
streetnames is a website that lets you test yourself to see how many streets in San Francisco you can name. It mixes together data from Google Maps and the OpenStreetMap project.

eatnum.com is a website that I made for accessing the USDA's nutrition database. It's fast, configurable, and doesn't have any ads.

lmnopuz is a web-based collaborative crossword server that my friend Evan and I wrote many years ago. I think it turned out pretty well, considering that neither of us knew much about programming for the web when we started. Another friend started porting it to Google Wave during the brief period when Google Wave was a thing.
smartychat is a XMPP/Jabber/Google-Talk bot for group chats. Some friends and I used to use a multiplexing chat bot called PartyChat for group-chatting within our Gmail accounts. It was down one weekend, so I spent a boring Saturday banging out a quick replacement in Ruby and jokingly named it "smartychat". The original PartyChat was later ported to Google App Engine and then EC2 (I guess?) and now doesn't exist (I think?). If you want to look at my code as an example of an XMPP bot, it's still there.
audioscrobbler is a Ruby implementation of the Audioscrobbler plugin protocol, used by music-playing applications to submit playlist histories to Last.fm. I don't know if this protocol is still in use, but it looks like the gem is still hosted by RubyGems.org.
trie is a Ruby implementation of a trie data structure, well-suited for storage and prefix-based lookup of strings or other sequential data. It looks like there's also a gem at RubyGems.org.
Gearman "provides a generic application framework to farm out work to other machines or processes that are better suited to do the work". I've never actually used it, but I was bored and looking for a project, so I wrote a Ruby API for communicating with Gearman servers. It turns out that writing tests for client-server interaction is kind of neat. The library looks like it is (was?) under development by other people at this GitHub repository now.
Typhoon is (was?) a Usenet server created by Highwinds Software. I wrote a couple of Perl scripts in 2003 or 2004 for a previous job and haven't touched them since then, but they may be useful if you're somehow still using it. radius_auth.pl is an authentication wrapper that lets Typhoon check users against a RADIUS server. sync_active.pl is a cheesy script that downloads the list of newsgroups from ISC's FTP site and brings the server's active file into sync with it (parsing control messages is a better route to take, though).
dmc is an OpenGL-based media center program that I used to run circa 2003 on a small PC that was hooked up to a stereo and television. It plays MP3s and IT/S3M/MOD/XM modules using the FMOD library, runs arcade, NES, SNES, and Genesis games using a variety of emulators, reads M3U playlists and ID3v1 tags, has some neat graphical effects (translucent zooming text, neat water-rippling effect on backgrounds, text flying all over the place on the music player screen, things happening in time with the music, etc.), supports joypads and IR transmitters, and is themable.




Reflect is a small puzzle game that I wrote in JavaScript a long time ago to give myself a chance to play with the <canvas> element. The goal is to place the blue mirrors such that the red beams hit the yellow targets.

Epplets were applets for the Enlightenment window manager way back in the late 20th century. E-Flame is a nice-looking system load monitor, E-Mount lets you mount and unmount drives, and E-Netgraph graphs network utilization. They used to, and may still, work with Enlightenment 0.16. I don't have any screenshots lying around, unfortunately.