DBML Tools VSCode extension with Go LSP server
A while ago I wrote about dbml-tools, a Go CLI for converting between live databases, DBML, SQL, and Graphviz diagrams. The CLI works fine in a terminal, but the moment you start editing DBML files by hand you want the usual editor niceties: red squiggles when you mistype a column, jump-to-definition on a foreign key, rename a table without hunting through references. That is what the DBML Tools VSCode extension delivers. ...
PuzzleHike.app v1 released!
I am happy to announce that PuzzleHike.app has reached its first stable release. PuzzleHike is a web application for organizing and walking puzzle hikes, where each waypoint on the route asks you a question and the answer unlocks the next leg of the walk. Think of it as GeoCaching, but everything is virtual. There is no plastic box hidden under a rock, no logbook, and no muggles to worry about. The puzzles live on your phone and the location checks happen against the GPS coordinates of the waypoints. ...
Tunnel Launcher puts your SSH tunnels in the tray
I am proud to release Tunnel Launcher: an open source GUI for managing SSH tunnels that is written in Go and built on top of the Fyne toolkit. It lives in the system tray, lists each configured tunnel with a click-to-toggle status icon, and reads your existing ~/.ssh/config so HostName, User, Port, IdentityFile and ProxyJump just work. Although the application has the potential to run on many platforms it is currently only tested under Debian (based) Linux and Windows 11. For a MacOS release I may need your help. ...
Local voice generation for telephony with Piper
I just published a Piper Voices TTS installer script, it turns a Linux machine into a local and offline voice generator for phone systems. It downloads the rhasspy/piper neural TTS binary and a set of pre-selected voices (120 MB each), then renders each test phrase twice. Once as a regular WAV file, and once as an 8kHz mono μ-law file that you can drop straight into a SIP PBX’s audio directory. No cloud accounts, no API keys, no per-character billing. ...
Reclaim used Yealink phones with multicast PnP
Yealink desk phones are everywhere on the second-hand market. Operators retire them in batches, resellers list them by the pallet, and they show up on Marktplaats and eBay for a fraction of the new price. The catch is that a lot of those phones are still administratively “owned” by the previous operator, even after a factory reset. In this post I will explain how I’ve put my own configuration on a set of phones that I bought, without asking Yealink (or the previous owner’s reseller) for permission. This post explains why that is harder than it sounds, and how multicast SIP PnP lets you do it anyway. ...
DBML: database schemas in plain text for genAI
Generative AI works best when everything is plain text. Code, configuration, documentation, data, the more you can represent as readable text files, the more effectively an AI agent can reason about it and transform it. Database schemas are no exception. You can dump a schema as SQL DDL and hand it to your AI agent, and that works. But SQL DDL is imperative and verbose; it tells you how to create tables, not what the schema looks like. DBML (Database Markup Language) takes a different approach: it is a clean, declarative, database-agnostic language for defining schemas that both humans and AI can read and work with comfortably. ...
GitHub export tool for open-source maintenance with AI
I have written a command-line tool in Go called github-export that exports all GitHub issues, pull requests, releases, labels, and milestones from a repository into a local folder as plain markdown files. What makes it different from existing tools is that it syncs incrementally and generates event files that an AI agent (like Claude Code) can pick up and act on. This lets me maintain my open-source projects with AI assistance. ...
Human-Crafted Software Manifesto
For years we have been told that speed is everything. That shipping faster is the only metric that matters. We are being told that the backlog is dead, that human bandwidth is a bottleneck, and that the future belongs to whoever presses the AI’s generate button hardest. We reject this. Not because we fear change, but because we have used these tools, and we have seen what happens when people stop caring about the output. We have seen skills abandoned, standards dropped, and products shipped that no one can explain, maintain, or bring themselves to care about. We have been told this is progress. ...
PathQL: Nested JSON queries
SQL gives us rows and columns, while APIs usually need nested JSON. That mismatch is small, but it creates a lot of repetitive code. Most backends choose one of two strategies: use a join and transform the resulting rows into nested JSON, or run multiple queries (often one per table) and then match each result set back to its parent. That code is not hard, but it is everywhere. And as Robert C. Martin reminds us in Clean Code, duplication is a design smell, even when each copy is “small”. PathQL is my attempt to remove that duplication while keeping SQL in the center. ...
Merge PHP projects into a single file with phpfilemerger
I wrote phpfilemerger, a small CLI tool that takes a PHP entry point and all of its class dependencies and produces a single self-contained PHP file. It uses an AST parser to resolve dependencies properly, so the output is ordered and ready to run. Use case: PHP-CRUD-API I maintain a PHP project that is distributes as a single file (PHP-CRUD-API) and phpfilemerger automates the process of building. It produces that one-file distribution, keeping class order and namespaces intact so the merged file works just like the original project. It statically analyzes your codebase using PSR-4/PSR-0 mappings and inlines all dependencies in the correct order. ...