Architecture decision records for coding agents
Evolu now writes down the decisions no single file owns as short architecture decision records, adapted for AI agents working in parallel: named, not numbered, with proposals agents must not…
Show page titles on Firefox's pinned tabs
I love vertical tabs. I used Tree Style Tab for years, then switched to Sidebery and recently to Firefox's native vertical tabs . I like them, but I was annoyed how pinned tabs looked. By default…
GoNIX and gokrazy: two ways to run Go on bare Linux
Both put a Go userland on top of the Linux kernel, but one wants to be a small UNIX you can read in an afternoon and the other wants to be an appliance with nothing you don’t need.
Exporting Local WeChat Voice Messages on macOS
A mate wanted to keep some WeChat voice messages as ordinary audio files and asked me to help. It sounded like a small conversion job: find the files, turn them into MP3s, and give them sensible…
What a RedNote Share Link Can Reveal
I came across on X that checks whether a shared link reveals the sharer’s social account. I was curious: when I send someone a post, what else goes with it? I started by looking at the request…
Stof 0.10: Safe by Default, Errors You Can Read, and a Language Server
Stof 0.10 makes embedded documents sandboxed by default, with time limits and an HTTP allowlist, adds readable errors with locations, using declarations, destructuring, a language server for editors,…
Introducing Fence: A Markdown Editor in Elm
Fence is an Elm and Electron Markdown editor with live preview, workspace search, and export. Version 0.7.0 adds ELK diagram layout, theme-aware Mermaid rendering, and pan and zoom.
Markdown files that execute
I keep forgetting how to release my own software. My major project Clientele has a PUBLISHING.md file with every step written down, but I release so rarely that I end up with the file open in one…
I built a chess puzzle plugin for Kobo
A KOReader plugin that puts Lichess puzzles on my e-reader, so I can do a few before bed without picking up my phone.
Scheduled events editor
Scheduled events have existed in ZenGM for a long time, mostly to support the historical real players mode in BBGM. Beyond that built-in mode, they've mostly been reserved for custom roster file…
Popover API and dialog: Building Native Modals Without a Modal Library
Most modal libraries exist to solve four problems: stacking the overlay above everything else, trapping focus, closing on Escape or an outside click, and wiring up the accessibility attributes. HTML…
Drawing Genealogy Graphs. Part 3: Genealogy Graph Positioning
Intro This is the third post in a series about building and rendering genealogy graphs. You can see all posts in the series here: /tags#drawing-genealogy-graphs-series . In the first post , I…
I hate QuickBooks Online, so I cloned it
TL;DR: I built wanderbooks . It's a free, open source, formally verified double-entry accounting engine. The only way to change your books is by talking to an AI (Claude Code or Codex) over MCP. The…
How to use Vue DevTools with Void
With this quick Promise-based utility, it's easy to write type-safe unit tests for Vue composables.
Tree RL
An unbiased policy gradient estimator for branching rollouts
SPLASH/ISSTA 2026
I have just returned from SPLASH 2026, which was colocated with ISSTA in Oakland, California. This was my first academic conference, and I thought it might be worth writing down some initial thoughts…
Cleaning up after a Camel
Now that my port of CamelForth-80 to the Sega SG-1000 is sort of working, it’s time to get it working better. There’s a lot of undone odds and ends and little bugs that I need to take care of before…
We CanCanCan fix everything
It took me a while, I know, but two new versions of CanCanCan are here: 3.7.0 is out already, and 4.0 is coming. Here is what changes and why I have two of them.
zot continuous: Agents That Survive
A persistent, recoverable execution layer for zot. The whole conversation lives in a durable store instead of in the running process. That one decision makes a crash a pause, and lets you pick up the…
agent-shell 0.87 updates
It's October. New month, new agent-shell update. If you missed the last post, have a look at the 0.78 update. While the latest changes are focused primarily on bugfixes and polish, we have a handful…
Scroll-triggered animation as the missing piece for scrollytelling on the web
Scroll-driven animations are one of my favourite things in CSS. But if you have ever tried to build an interactive story with them, you probably noticed that scrubbing is not always what you want.…
The cradle
Starting code · Completed code I learned top-down recursive-descent parsing from Jack Crenshaw’s Let’s Build a Compiler!. I’ve used it many times since, including for a custom color formatter I wrote…
Collection Expression Arguments Fix the Comparer Problem in C# 15
C# 15 adds with(...) arguments to collection expressions, so you can finally set a comparer or capacity without abandoning the [a, b] syntax.
gg, weeks 8 to 11: a pond, fog, night, and a month on a laptop
Four weeks on a laptop with an integrated GPU: the pond gets a surface, fog becomes a medium, the goldens leave git, and night stops being black.
agent-shell 0.87 updates
It's October. New month, new agent-shell update. If you missed the last post, have a look at the 0.78 update. While the latest changes are focused primarily on bugfixes and polish, we have a handful…
IPv4 Parsing: Having Your Cake and Eating It Too
SWAR Zig SIMD IPv4Again?Once again I got hooked on the deceptively simple problem of parsing IPv4. This time it happened while reading 192.168.1.1 is too short for SIMD. The gist: the fastest parser…
Jot: capture without leaving the note
An idea arrives while you are in the middle of something else. In Joplin, New to-do creates an empty note and opens it: the note you were reading is gone, and Back lands at its top. A user asked in…
Dashboard layout using CSS Grid Lanes and <code>align-self:stretch</code>
CSS Grid Lanes supports stretch alignment along the stacking axis, allowing items to fill any remaining space left between other items, and avoid a jagged end edge. See Aligning items within their…
Load All Ancestor direnv Files
Make direnv load every .envrc file in a directory's ancestors, not just the closest one. direnv has a built-in source_up function for this, but it must be added to every .envrc file and I…
Devoxx Belgium Mutants Talk Posted
My talk from Devoxx Belgium, “Kill All Mutants! (Intro to Mutation Testing)”, has been posted at https://www.youtube.com/watch?v=AsVt_dzTmN4.
Jujutsu Has No “Create a Branch” Step, and That Finally Made Git Branches Click
Jujutsu has no “create a branch” step. Detached HEAD, anonymous branches, and bookmarks helped me finally understand why Git branches are pointers, and why Jujutsu uses bookmarks instead.
On-device embeddings with EmbeddingGemma 2 in the Koog-based Confetti AI agent
In an earlier article we added semantic search to the Koog-based AI agent in the Confetti Compose Multiplatform sample. That used Gemini both for the LLM driving the agent and for the embeddings…
You want minimalist? Here’s minimalist
.minimalize { background-color: #fcd709; outline: none; border: none; padding: 10px 20px; font-size: 24px; border-radius: 20px; margin-bottom: 10px; } Every once in awhile, I see a beautiful,…
1851. Minimum Interval to Include Each Query
class Solution: def minInterval(self, intervals: list[list[int]], queries: list[int]) -> list[int]: left = intervals[:] # Sorting the intervals by the left left.sort() tq = [] for i, n in…
The geometric model of maintenance
James Shore posits that each person-month spent writing code results in 10 days of maintenance in the first year, then 5 days every year after that. Naïvely interpreted, this is a threshold-based…
My Current AI Coding Setup
A few people have asked how I’m coding with AI at the moment, so here’s a quick rundown of my setup, with links to everything in case you want to copy it. The short version is that I run…
Reverse Engineering with AI Agents: REA
Normally, we write source code and use a compiler to turn it into machine instructions that a CPU can execute. Reverse engineering starts from the other end: we have the executable, but not…
Cleaning the Heap - Helping the Go Compiler
cleaning-the-heap
✍🏻 Sortable Tables with Progressive Enhancement
Many years ago, I made a little jQuery plugin called Easy Sortable Tables. It works exactly as promised: point it at a table and it upgrades the UI so a reader can sort the rows by clicking a column…
Adding custom Thor commands to your Rails app
Thor is a really nice command-line runner, with much nicer support for arguments than Rake imo. The Rails framework supports both, but since Rails 5.1 most Rails’ built-in commands (like bin/rails…
Scriptable Zig
There is a preamble you can add to any Zig file to make it runnable as a script. #if 0p=$(mktemp -t tmp.XXXXXXXXXX.zig) cc -x c -E -P $0 > $p zig run $p exit $? #endif const std =…
Row-Group Control, Faster S3 Reads, Footer Caching: Hardwood 1.1.0.Beta2 Is Out
Table of Contents Writer Improvements Performance Improvements Footer Caching and Reuse Id-Based Access to Dictionary-Encoded Columns Also in This Release I’m happy to announce the release of…
How to Set Up Signup Attribution in PostHog Behind a Cookie Banner
Your cookie banner is hiding where your signups come from. PostHog never sees the page they landed on, so nearly all of them show up as direct. Here’s the fix, step by step, with all the code.
[Thoughts] October 12, 2026
RIP Dennis Ritchie, it’s been 15 years now… Thank you for using RSS and subscribing to my website! If you have any thoughts, you can always respond privately to this post via email.
PostGIS vs GeoPandas vs DuckDB: The One Spatial SQL Engine That Runs On Your Laptop
Most geospatial tools were not built with spatial as a core feature. Spatial got bolted on later, and you can feel it the moment you try to run a real query. I ran the same four spatial queries…
First steps in bare-metal programming using UEFI -- part 5
The fifth part of a series about bare-metal programming for x86 PC-type computers, using Linux for development. This article is about handling files using EFI's Simple File Protocol.
Elo
The Elo rating system provides a method to calculate the relative scores of two players in games like chess. Beating a stronger player should earn you more points than beating a weaker one, and the…
The Disappointing Death of Deno: What Happened and the Perils of Venture Capital-Funded Open Source
A breakdown of the history of Deno, the emergence of Bun, and a reaction to the Cloudflare acquisition by a developer who went all-in on Deno years ago.
Event Sourcing: A close look at the projector for values
In this part of my event sourcing series, we look at implementing the projector for values (uni-temporal events / normal event sourcing). You’ll see the full source code for our ValueProjector,…