RSSAmplifier

Blog

McGinnis, Will

Recent content on McGinnis, Will

mcginniscommawill.comRSS feed ↗535 posts

Latest posts

Prove the Test Can Fail: Mutate the Fix

After you write the test that goes with your fix, revert the fix and watch the test fail. That takes about thirty seconds, and no other single habit has done as much for my confidence in a diff. 
 That’s it. That’s the whole technique. I now consider a regression test unverified until I’ve seen it red, and I ask for the same from anything that writes code on my behalf.

Stars, Views, and Clones Across 63 Repos

I released version 0.2.0 of stargazers last week, a CLI I use to pull the event data sitting behind a GitHub star count, and ran every command against my own account. Then I ran it again, because an account-level query misses the largest thing I have worked on. category_encoders lives under scikit-learn-contrib , so as far as /users/wdm0006/repos is concerned it does not exist. 
 Including it…

Running GitHub Actions Efficiently

I recently went through the GitHub Actions configuration in every repository I own, which is somewhere north of seventy, and tuned them all in one pass. Doing the same job that many times in a row is clarifying. You stop debating and start noticing which changes actually move the number. 
 This is the checklist that came out of it, in the order I’d apply it.

Rampart v0.8: Full Fleet Coverage and Better Ruleset Support

Rampart v0.8 is out. It audits your private repos, handles GitHub rulesets correctly, catches mistakes in your config file, and behaves properly in CI.

Sharing 100 Requests With Every User You Have

Most API rate limits are a personal problem. You get your bucket of requests, and if you blow through it, you wait. Strava’s read limit is a different animal: roughly 100 requests per 15 minutes and 1,000 per day, shared across your entire application. Every user of Pedal Wrencher draws from the same bucket. One greedy sync loop doesn’t throttle one athlete, it throttles all of them.…

What a Month of Portfolio-Wide Engineering Looks Like

I’ve written about the pieces of my setup separately: Swamp as the automation backbone, the Open Knowledge Format as the memory, and distilling skills out of that memory. This post is the output side. For the last month I’ve had a loop running continuously across every repository I own, and I want to describe what came out of it, because the shape of the work surprised me more than the…

Programmable Feeds: RSS Is the Bus

When I launched emit it did one thing: poll your blog’s RSS feed and email new posts to your subscribers. Two months later it does considerably more than that, and the interesting part is that almost none of the new surface required new plumbing. It all fell out of one decision made early for boring reasons, which is that everything inside the system is a feed.

This Blog's Newsletter Now Runs on Emit

The signup form at the bottom of this post now points at emit , the RSS-to-newsletter service I launched on Friday . When I publish here, emit picks up the RSS feed and sends the post to subscribers. This site is now customer zero, and this post is about what that wiring looks like and what it taught me.

Emit: Pay for Emails, Not Subscribers

I’ve launched a new thing: emit , a service that turns your blog’s RSS feed into an email newsletter. Point it at your feed, and when you publish, your subscribers get an email from your own domain. That part is table stakes. The reason I built it is the pricing.

MCP Goes Stateless, and Sampling Goes With It

The 2026-07-28 MCP spec is the biggest revision since the protocol shipped. The headline is that sampling is deprecated, which stings a little because I wrote a whole guide telling you to build on it . But sampling didn’t get removed because someone disliked it. It got removed because MCP stopped being a stateful protocol, and once you make that call, most of the rest follows.

Pedal Wrencher Is Back

In March 2015 I launched a weekend project called Pedal Wrencher . It connected to your Strava account, watched your mileage, and texted you when your chain was due for a replacement. It ran for about three years, sent a thousand or so notifications , and then died in 2018 when my startup got acquired and every side project I had fell over from neglect. 
 As of this month, it’s back.…

Easy Beans (Borracho-Style Pinto Beans)

These are the beans I make when I’ve got scrap pork belly kicking around and no particular plan. They start life as charro or borracho beans — the beer is the “borracho,” Spanish for drunk — but I take every shortcut available. Canned pintos instead of dried, whatever fatty pork trim I have, and a long lazy simmer to make it all taste like it took more effort than it did.

Charred Roasted Salsa

Raw salsas are great, but roasting is where you get that deep, smoky, restaurant-style flavor that makes people ask what you did. The whole trick is char. You want the tomatoes and chiles to get genuinely blackened in spots under the broiler, because those burnt edges are where all the flavor lives once it hits the blender. 
 I make this on the same afternoons I’m firing up the grill…

Distilling Skills From a Knowledge Base You Build While You Work

This is the third post in a small run. The first was about Google’s Open Knowledge Format , a tiny markdown spec for handing curated context to AI agents. The second was about Swamp , a framework for running deterministic, searchable automation that agents operate. This one is the payoff: what you get when you point the two at the same problem. The pattern I want to describe is a loop that…

PyGeoHash v3.3.1: A Round of Sharp-Edge Fixes

PyGeoHash v3.3.1 is out on PyPI. This one is not a performance release like the June run of optimization work was, it is a cleanup release. It goes after the sharp edges that were still hiding in the C extension, tightens up a couple of functions that returned the wrong answer in corner cases, and finally ships the typing marker that should have been in the wheel a long time ago.

Swamp Club: Deterministic Automation for AI Agents

Last week I wrote about Google’s Open Knowledge Format and mentioned in passing that I run a background orchestrator that keeps a fleet of coding agents busy across my repos around the clock. A few people asked what actually runs that thing. The answer is Swamp , and it’s interesting enough on its own that it deserves its own post. So this one is about Swamp itself, with my autopilot…

Mexican-Style Grilled Meat Marinade (With a Little Miso)

Every summer I end up with some version of a carne asada marinade in a zip bag in the fridge. It’s the kind of thing you make once, love, and then never write down, so every time you start from scratch and half-remember the proportions. This is me finally writing it down. 
 The base is a pretty classic bright, citrusy carne asada situation: lime, a little orange juice, a can of Sprite…

Setting Up Lexicon with Claude Code and Claude Desktop

I’ve gotten a few questions about how the MCP integration in Lexicon actually works in practice. The short version: you add one config entry, and your entire prompt library shows up as slash commands in Claude Code. Here’s the full setup.

Google's Open Knowledge Format

Back in June, Google Cloud published something called the Open Knowledge Format, or OKF. It landed pretty quietly for what it is, which is a serious attempt to standardize how you hand curated context to an AI agent. I’ve been using it for about a month in a project of mine, and I’ve come around to thinking it’s one of the more sensible ideas to come out of the whole agent gold…

Building Reusable Prompt Templates in Lexicon

The simplest use of Lexicon is saving prompts you type a lot. But the template system is where things get more useful. Instead of saving static text, you can build parameterized prompts that adapt to whatever you’re working on.

The Unified Theory of Food: A Salad-Sandwich Taxonomy


 
 When you have eliminated the impossible, whatever remains, however uncomfortable, must be a salad or a sandwich. 
 
 
 Attributed to the Structural Starch school apocryphal 
 
 
 
 
 
 
 Copy 
 
 
 

 Abstract 
 The prevailing folk taxonomy of food is a mess. Consumers routinely operate with dozens of overlapping and…

idea.log Now Has an MCP Server

The macOS version of idea.log now ships with a built-in MCP server. Your AI coding agent can read your ideas, create new ones, and manage tags without you ever opening the app.

Lexicon: A Prompt Library for macOS

I wrote about building a prompt library with MCP back in October. At the time, Lexicon was a side project I’d been hacking on to scratch an itch: I had too many prompts scattered across too many places. Some lived in my head, some in a notes file, some in old chat histories I’d never find again. 
 Since then I’ve been using it daily, and it just shipped to the Mac App Store.…

Share Ideas Between idea.log Users with Universal Links

You can now share ideas from idea.log with other people. Tap share, pick “Share with Friend,” and send the link through iMessage, Slack, email, whatever. If the recipient has idea.log installed, the idea gets created in their app automatically.

Automating App Store Connect with Fastlane (and Letting Agents Drive)

I ship a handful of small Mac and iOS apps. Lexicon , idea.log, Evergreen. None of them are big businesses, which means none of them justify me spending an afternoon clicking around App Store Connect every time I want to fix a typo in the description or bump a price. 
 App Store Connect is fine as a website. It’s just slow in the way that any web UI is slow when you have to do the same…

idea.log Comes to macOS

idea.log is now on macOS. Same app, same data, native Mac UI.

Into the C: Making PyGeoHash Decode Twice as Fast

This is the third post in a small thread about PyGeoHash performance. First I benchmarked it against the field , then I trimmed the Python wrapper that sat in front of the C extension. That wrapper work got encode within a hair of the C++ python-geohash library. But decode was still about four times slower, and I had already established that the slow part lived in the C extension itself. So this…

Evergreen Skills - Teaching Claude to Manage Your Relationships

I’ve written a couple times now about Evergreen , the personal CRM I vibe coded in Swift. The short version: it’s a local-first app, now on Mac, iPhone, and iPad, that stores your contacts, interactions, relationships, and follow-ups in a SQLite database on your own devices. No accounts, no ads, no telemetry, and your data never touches my servers. It recently picked up iPhone and iPad…

Evergreen Comes to iPhone and iPad

I’ve written a few times now about Evergreen , the personal CRM I vibe coded in Swift to keep track of the people in my life. Up until now it lived in exactly one place: my Mac. That was fine when I was sitting at my desk adding contacts after an Atlanta AI dinner. It was a lot less fine standing in a hallway at a conference, phone in hand, trying to remember the name of someone I’d…

Optimizing PyGeoHash Without Touching the C

A few days ago I benchmarked PyGeoHash against six other geohash libraries . The summary: we sit comfortably ahead of every pure Python implementation and a step behind the ones that drop into Rust or C++. The number that bugged me was decode. PyGeoHash decodes a geohash in about 1,500 nanoseconds. python-geohash , the C++ library, does it in about 220. We have a C extension too, so why were we…

Managing Context at Organization Scale

I’ve written a lot of CLAUDE.md files. One for every project. Each one captures the stuff that doesn’t fit in code or docs: how the project is laid out, the conventions we follow, where things deploy, who to ask when something breaks. 
 For a single project, that’s enough. You write the file, you check it into the repo, and any new engineer (or AI assistant) has the context…

Yakitori Negima: Chicken, Scallions, and a Pot of Tare

I bought a little yakitori grill , one of those long, narrow konro boxes, and I am completely obsessed. There’s something about the binchotan charcoal glowing away while you fan skewers over it that makes you feel like you actually know what you’re doing, even on the first try. I made negima, the chicken-and-scallion skewers, and I don’t think I’ll ever stop. 
 The…

Benchmarking PyGeoHash: Where It Lands Against the Field

A while back the Apache Superset project swapped out python-geohash for PyGeoHash . The reason was painfully familiar to anyone who has shipped a library with a C extension: python-geohash ships a C++ extension that refuses to build in the slim Docker images a lot of teams run, and the build just falls over when there is no compiler in the container. PyGeoHash ships pre-built wheels, so it just…

The OODA Loop for Startup Engineering

I’ve written before about PDCA as a framework for systematic quality control. PDCA is great when you have time to plan carefully, run controlled experiments, and analyze results. But startups often don’t have that luxury. The market shifts, a competitor launches something, your biggest customer changes their requirements, and suddenly your carefully constructed plan is irrelevant.…

Rampart v0.7: Push Allowlists for Protected Branches

Rampart v0.7 adds support for the one piece of GitHub branch protection it was missing: the push allowlist.

Pasta e Piselli: A Simple Italian Pasta with Peas

Pasta e piselli is one of those classic Italian dishes that nobody seems to know about, which is a shame because it might be the most weeknight-friendly pasta you can make. It’s pantry food in the best sense: peas, onion, a bit of pancetta, and whatever short pasta you have lying around. The Neapolitan version cooks the pasta directly in the broth with the peas, so you end up with something…

Spring Reading List 2026

Following my winter reading list , here’s what I’ve been reading this spring. 
 The Fish That Ate the Whale 
 by Rich Cohen 
 The story of Sam Zemurray, a Russian immigrant who started by selling ripe bananas off a train car in Alabama and ended up running the United Fruit Company, one of the most powerful corporations in American history. Along the way he overthrew…

The Full McGinnis Stack: An Opinionated Python Developer Setup

Over the past year or so I’ve been building tools to solve specific annoyances in my development workflow. A task manager here, an MCP server there, a CLI for a thing that bugged me. At some point I looked up and realized I’d accidentally built an entire stack. 
 This post ties it all together. If you’re a Python developer who uses Claude Code (or another MCP-compatible…

Using Claude Code Hooks to Force uv

I wrote recently about why uv changed how I think about Python projects . The short version: I use uv for everything now. But Claude Code doesn’t always get the memo. 
 Even with instructions in your CLAUDE.md, you’ll occasionally watch Claude reach for pip install or bare python or pytest instead of routing through uv. It’s not that Claude ignores the instructions.…

uv Changed How I Think About Python Projects

I’ve been writing Python for a long time, and for most of that time, packaging has been the worst part. Not “mildly annoying” worst. “I’m going to close my laptop and go for a walk” worst. The tooling was fragmented, slow, and confusing in ways that made experienced developers feel like beginners and made beginners feel like they’d chosen the wrong…

Code Archaeology with AI

Every company has a closet full of old code. Maybe it’s a Perl script that generates invoices and nobody knows how it works. Maybe it’s a Java monolith that was “temporary” in 2014. Maybe it’s a MATLAB folder from grad school that you swear you’ll get back to someday. I recently revived some of my own old MATLAB code and along the way learned a lot about how AI…

Technical Debt Is a Leadership Problem

I’ve been on both sides of the tech debt conversation. As an engineer, I complained about it. As a manager, I created it. Neither side has the full picture, and that’s exactly the problem. 
 Tech debt gets treated as a technical issue. Engineers identify it, engineers want to fix it, and engineers get frustrated when they can’t. But the decisions that create tech debt and the…

You Don't Need a Justfile

I’ve written twice now about Makefiles: once about why they’re useful and once about advanced patterns . So you can probably guess where I stand on this. But I keep getting the same response from people: “Have you tried just? Have you looked at Pixi? Why not use a Taskfile?” 
 I have. And I keep going back to Make.

Advanced Makefile Patterns for Python Projects

I wrote previously about why Makefiles are useful for Python projects . That post covered the basics: what Make is, why you’d use it, and some simple examples. But I’ve been using Make for long enough now that I’ve accumulated a collection of patterns that go well beyond make test and make lint . Some of these are clever. Some are arguably too clever. All of them have saved me…

Data Science Career

Navigating a Career in Data Science 
 I’ve been in and around data science for over a decade now, and the field has changed dramatically in that time. The job titles, the tools, the expectations, even the definition of what a data scientist does have all shifted. What hasn’t changed is that people still struggle with the same career questions: What should I specialize in? Should I…

Hiring Data Scientists: What Actually Matters in 2026

I’ve been hiring data scientists for the better part of a decade now, and the job has changed more in the last two years than in the previous eight combined. The interview playbook I used in 2020 is almost entirely obsolete. Not because the fundamentals of statistics or machine learning changed, but because the practical reality of what a data scientist does day-to-day has shifted…

A Full SDLC with MCP Servers

I’ve been building and using MCP servers for about a year now, and at some point I realized they’d quietly grown to cover most of the software development lifecycle. Not in a grand, planned-out way. Each one solved a specific annoyance, and taken together they form something more complete than I intended. 
 Here’s how they all fit together.

Rating Systems Compared: Choosing the Right Algorithm

Over the past few months, we’ve taken a deep dive into the world of rating systems through the lens of Elote , my Python library for implementing and comparing competitive rating algorithms. We’ve explored eight different systems: 
 
 Elo - The classic chess rating system 
 Glicko-1 - Elo with uncertainty tracking 
 Glicko-2 - Adding volatility to the equation 
…

mutmut-mcp: Tests, CI, and Survivor Prioritization

mutmut-mcp wraps the mutmut mutation testing tool so an agent can run mutation tests and act on the results without you doing anything. I wrote about it in the practical MCP use post, where I described the basic workflow: the agent runs mutmut, looks at surviving mutants, writes tests to kill them, validates, and repeats. 
 That workflow still works well. What didn’t work well was the…

writing-tools-mcp: Still Useful, Now With uvx

writing-tools-mcp is the MCP server I’ve written about the most, starting with the initial deep dive and then the MCPB packaging update . It’s also the one I use the most consistently. Every post on this blog goes through it. 
 This update is minor compared to the others. writing-tools-mcp was already in good shape: 144 tests passing, CI pipeline in place, solid feature set. The…