-
Every Level Is Winnable, and I Can Prove It
My next game builds its levels fresh every time you play — rooms, corridors, locked doors, hidden keys. Which raises a terrifying question: what if it builds one you physically can't finish? Here's how I stopped blindly trusting the generator and started proving it wrong.
-
I Tore Out the Renderer. Again.
When I built my first game I ripped out a renderer I loved and rebuilt the world from scratch. For the second one I did it again — only this time there are no models, no meshes, no geometry in the usual sense at all. Every wall and every enemy is an equation. Here's why I keep doing this to myself.
-
The Sound I Could Not Fake
I wrote a whole post bragging that my games ship no asset files — every pixel and every note generated in code, the lot small enough to fit on a floppy. Then I started the second one, and a monster in the dark made me break my own rule. Here's why sound was the one thing I couldn't synthesise, and how I broke the rule without betraying it.
-
One Television, One Kilobyte
Something set me thinking about the Sinclair ZX81 today — the first computer I ever touched, when I was twelve. The sublime manual, the housework I did to earn telly time, the tape that never loaded, the RAM pack that lost everything, and the unbridled joy of the first program that was properly mine.
-
Better Late Than Never
An afternoon with no business case whatsoever: I opened the dead issue tracker of a PHP library I’d kept frozen since 2014 — eighty-five issues, the newest a decade old — and cleared the lot. Not by mass-closing, but by reading every one, fixing the two that were genuinely still broken, and replying by hand to all eighty-five people who’d once filed into a void. This is the whole story: the humane method, the gnarliest bug (a one-character CSS mistake that survived ten years), and what a dead repo taught me about the actual shape of software maintenance.
-
My AI Had Amnesia, So I Built It a Memory
Claude can refactor a Metal renderer at 2am and forget the entire estate by morning. Here is how I gave it a permanent, self-maintaining memory of all of Jorvik Software — three layers, one local LLM running on my own machine, zero cloud, and a fistful of bugs that lied to my face along the way.
-
The Shortcut I Never Meant to Press
There is a key combination on every Mac that toggles display mirroring, it sits one slip away from shortcuts you use all day, and I kept hitting it by accident at exactly the wrong moment. So I built a tiny app to swallow it. The build had a twist: the key I was trying to block turned out not to be the key I thought it was.
-
Strataris: The Screensaver That Became a Game
Five months, a lot of swearing, the occasional actual tear, and a stubborn rule that the whole thing had to fit on a floppy disk. My first native game is finished. Here's the messy story of how it got here.
-
The Details Are the Software
Tugboat is an internal-only tool, used by exactly one person, and almost nobody will ever see its menu-bar icon. I reworked that icon anyway, so it shows — in real time — which edge of the screen the Dock is actually living on. This is a post about the smallest of details: why they matter, why they're the line between hand-crafted code and AI slop, and the other invisible little things scattered across the Jorvik suite.
-
The OS Upgrade Tax
Two apps, three Tahoe regressions, one afternoon — the price of shipping a macOS suite through an OS upgrade.
-
The Column I Couldn't Copy
Last week I needed to copy a single column out of an HTML table in an email, and discovered that the boring solution — copy the whole table, paste it somewhere, trim it back — is a fifteen-second tax on a one-second intention. So I built CopyLens. Draw a rectangle anywhere on screen; if there's text inside, it lands on the clipboard as text. If not, the cropped image does. Same gesture, two outcomes. Plus a full-disclosure note about how the OCR engine actually got built, which wasn't by me.
-
Rainy Day Isn't a Screensaver
Rainy Day shipped this past weekend. The product page calls it a screensaver. The bundle on disk is a regular .app — no .saver in sight. This is the story of why. A run-down of the macOS frictions that ended my attempt to build it the orthodox way: WebContent suspended within seconds of activation, an Apple SPI that no longer works in macOS 26, a CARenderer that returns blank frames, ScreenCaptureKit edge cases when the saver occludes the screen it's trying to read, multi-instance lifecycle thrash from System Settings previews, and the way ad-hoc signing burns TCC grants on every rebuild. And then the architecture I ended up with — LSUIElement app, SMAppService login item, idle-driven fullscreen NSWindow at screenSaver level — which side-stepped every one of those frictions in an afternoon.
-
Putting The House In Order
Two weeks of housekeeping on the Jorvik estate. It started with Spotlight launching the wrong version of an app, ended with a 1,100-line refactor of Release Manager, and surfaced about ten gigabytes of accumulated nonsense in between. This is the diary of the fortnight: what the audit found, what `ps` told me about my own apps, and why a clean filesystem is a clean countertop.
-
I Deleted Most Of My Release Manager
My Release Manager was a 1,600-line Swift pipeline that built, signed, notarised, packaged, and shipped every Jorvik app. Today it's a 770-line dispatcher, and the work it used to do happens in shell. This is the story of why I stopped reaching for Swift, and what I learned about treating the right tool as the obvious one even when it isn't the prestigious one.
-
The Icons Behind The Notch
MenuTidy was the app I'd quietly filed away as 'done' — collapses your menu bar, cleans up clutter, ships. Today I added a feature I'd been trying to ignore for months: a way to actually click the status icons that the notch on MacBook Pros has politely hidden behind itself. I also fixed a position-memory bug that had been quietly lying to users for months.
-
Default ON Was The Wrong Default
I changed the rendering format of the standard “background pill” option of our menu-bar apps. I set the default to “on”, propagated deployment across eleven apps in a sweep, and then realised it was silently changing settings for upgraders who'd never touched the toggle. The pill that came shipping with everyone's next update was a small surprise nobody asked for. A short lesson in `UserDefaults.register`, the difference between “fresh install” and “user with no preference set”, and why reversing a convention across eleven repos in one go is sometimes the only honest move.
-
The App I Needed At 1am
“I've lost my mouse pointer” demanded a tiny one-shot utility — and taught me a lesson in why “give the user a Terminal command” is a poor recovery flow when she doesn't have a mouse pointer. Building MouseCatcher, bundling it with ActiveSpace, and the install-permissions detour that nearly derailed it.
-
When the Stars Align (Final Cut)(Maybe)
The latest version of ActiveSpace is shipped. Third and final post in the stars-align saga: the 640×480 virtual display from the Redux turned out to be a perfectly valid second monitor as far as macOS was concerned, with the Dock and cursor both happily wandering onto it. A drift reposition, a cursor fence, and the satisfying deletion of a self-restart mechanism the data showed wasn't needed.
-
Screen Savers Still Exist
I built a screen saver, and why not? It's a full-screen canvas that activates when you step away from your desk. Some would call it a relic of the CRT burn-in past. I say it's a dashboard, a photo frame, an ambient display. It's just wearing the wrong name.
-
Fine, Apple. You Win
Three months of stubbornness, then an afternoon of capitulation. The follow-up to "The Deploy Problem Nobody Talks About": every Jorvik app now ships a signed .pkg installer alongside the .zip, closing most of the quarantine-and-translocation friction the previous post complained about. Why .dmg would have solved nothing, what macOS Installer actually does on your behalf, and — because no release week is complete without one — the story of a build pipeline that silently shipped one of my apps without its own bug fix.