Projects

A curated selection of things I've built, patched, ported, or stubbornly maintained long after the world moved on. Some solve real problems. Others exist purely because I was annoyed enough to write code about it.

Music & Audio

Audiqa

Everyone's renting their music now. Good for them. Some of us still own ours and would like a proper app to manage it — one that's fast, local-first, and doesn't phone home every time you press play.

Chromaprint, rewritten in Rust

Other people wrote Rust ports of Chromaprint. They produce the wrong fingerprints. This one produces bit-identical output to the C reference and beats it by 4% on throughput — despite the C version using Apple's hardware-accelerated vDSP. You're welcome.

Last.fm History Exporter

Downloads every scrobble you've ever made to JSON — artist, album, track, timestamp, the lot. Has retry logic because Last.fm's API will absolutely drop your connection after three hours and pretend nothing happened.

AI

Apple Mail.app MCP Server

Lets AI assistants read your email without sending a single token to anyone else's server. Everything stays on your machine. One Go binary, no dependencies, and an audit log because if something's reading my inbox, I'd like receipts.

URL Summarizer

Give it a URL, it gives you the gist. No UI, no browser extension, no twelve-step onboarding flow. Just a CLI that reads a page and tells you what it says so you don't have to.

Observability

AdGuard Home Prometheus Exporter

A Prometheus exporter that actually follows the official exporter guidelines — which, apparently, was too much to ask of the existing alternatives.

devtools

Pow Bonjour Advertiser

Broadcasts your Pow dev server over Bonjour so every device on the network just finds it. Written because testing on an iPad meant looking up your IP address every time DHCP felt like reinventing itself.

Ember.js extension for Capybara

Poltergeist clicked buttons before Ember was ready, so tests either failed randomly or passed for the wrong reasons. This gem monkey-patches the click to wait for the run loop. Require it and your tests start behaving like adults.