I work across a lot of different GitHub repos, and agents have made it a lot easier to produce code than to verify and merge it. I’ve found one of the best ways to keep things moving is to avoid building up too much of a backlog of PRs. I built prBar to show the open PR counts in my Mac’s menu bar, so I can see how much crud is accumulating and when to focus on clearing it.
Supply-chain attacks are a growing problem for anyone installing dependencies. An attacker compromises a maintainer account or publishes a malicious package, and an ordinary install brings their code onto your machine. In the Shai-Hulud npm attack, compromised packages used malicious post-install scripts to spread the attack.
The observed activity has grown sharply: Sonatype recorded 3,430 malicious-package advisories in 2025, compared with an annual average of 931 in 2021–2023. That’s one research team’s detection data, but it gives a sense of the change in scale.
I rarely need a dependency update right when it comes out, and researchers, registries, and other users usually spot compromises quite quickly, so waiting to install updates feels like an easy way to prevent most of these attacks.
npm-age-pin enforces this rule: select a release at least 72 hours old, pin its exact version, and install with installation scripts disabled.
I was at dinner in Uzbekistan with my friend Jordan, who’s spent much of the last few years backpacking around Africa, Central Asia, and everywhere in between. He suggested a game: pick a letter, go around the table, and take turns naming countries that start with it.
A few hours into coding with AI, a pattern shows up. The code looks clean. Abstractions make sense. Tests pass. And yet under concurrency, your rate limiter collapses because the counter isn’t atomic.
Here’s the formula nobody talks about:
failure= error rate × variance
Coding with AI massively increases variance. Even if error rate stays constant (big if), failures scale dramatically with output. After a few hours, you have 200 files of mostly okay spaghetti code and an AI who responds to your prompts with things like:
My family loves to play an obscure card game called “forty-fives” (45) popular in northern New England and Atlantic Canada.
We play an even more specific set of rules (the probabilistically most interesting and exciting variant!) where you sit across from a teammate and play another team of two. Each person “bids” for the number of points they expect their team can get in exchange for receiving four hidden cards in the “kitty” and choosing the “trump” suit that defines the hierarchy of cards. Many a game has been turned by our most distinct bid: “30for60” where a player who bids that they can get all 30 points in a hand is rewarded with 60 points if they do so.
Living thousands of miles away from anyone I’m related to is hard sometimes. The long tail of the internet had not produced a way to play online so I built 30for60.com: a fully functional version of the game complete with self-play trained bots that can join a game if we don’t have enough human players.
I don’t like opening my laptop to a wall of tabs from things I was doing the previous day: it slows my computer down and makes it harder to think. I used to use “The Great Suspender”[1], but what I really want is to just put everything away at the end of the day and start the next from a place of agency instead of momentum.
I made the Chrome extension Tab2Notes to do this. Click the extension, export all the tabs in the current window or across all your windows, pipe them to Apple Notes via the Shortcuts app. Bulk open the URLs with a paste when you want them back.
I use Parcel to track all of my deliveries. The app has an Amazon integration but I purchase a remarkable number of clothes, tech, and vintage aviation memorabilia on eBay.
I built eBay2Parcel to automatically import eBay tracking numbers into Parcel. Once a day it asks eBay for my recent buyer orders, filters for the ones that have a tracking number and haven’t been delivered, and sends them to Parcel.
I use Apple Music in large part because I’ve been rating songs there (and in iTunes before it) for over a decade. I also really dislike making playlists and Apple has a “smart playlists” feature that makes it really easy to programmatically include/remove music based on its rating and other attributes. Apple natively tracks play count, skip count, and genre, but the genre is usually one broad word the label picked, and plays and skips only mean something together: a song I’ve played 200 times and skipped 150 times isn’t a favorite, and one I’ve played 20 times and never skipped probably is. So I built PlaylistMint. PlaylistMint reads my library, classifies every track by energy, mood, genre, listening context, and language, writes the labels back into Music.app, and then builds playlists that combine those labels with my ratings and a calculated skip rate to reflect how much I enjoy the song.
A lot of the longer writing I do starts as a voice memo: I go on a long walk with just my recorder and exhaust all of the angles I can think of over an hour or two. I used to use online sites to do transcription but I didn’t love the idea of sharing these with a third party and the experience was kind of annoying so I built WhisperBatch: a native SwiftUI Mac app that uses WhisperKit to transcribe locally. Pick as many files as you’d like, choose a model, and save a transcript next to each recording. You can preview the waveform and crop audio, include timestamps, or export text, SRT, VTT, and JSON. The default model is large-v3-turbo; models download on first use, and transcription then runs locally using the cached model. There’s also a Swift CLI that shares the app’s transcription engine.
I’ve used Airtable as a custom ERP across a few businesses. I’ve always been annoyed by how difficult it is to bulk export/import attachments so I built bulkAirtable.
Preview on a Mac will merge two PDFs for you. It will also, in my experience, turn a pair of 2MB files into a 22MB one. Notion will export a second brain as a zip of folders named with 32-character hashes. A phone photo posted to a website is likely to carry timestamps and GPS coordinates unless you strip the metadata.
I got tired of solving each of those once and throwing the script away. tidyData is the drawer I keep them in.