← Back to Kevin's newslettersPublished: 2026 Jan 4

Hi friends!

While answering 40 questions to ask yourself every year, I realized I’d adopted a bunch of new tools over 2025. All of them have improved my life, so I want to share them with you so they might improve yours too =D

A common theme is that all of my favorite tools promote a sort of coziness: They help you tailor the spaces where you spend your time to your exact needs and preferences.

Removing little annoyances and adding personal touches — whether to your text editor or your kitchen — not only improves your day-to-day mood, but cultivates a larger sense of security, ownership, and agency, all of which I find essential to doing great work. (And making great snacks.)

Physical

Workshop space

Last summer we moved to a ground-level apartment, giving me (for the first time in my life) my very own little workshop space:

We’re just renting the apartment, so building a larger shed isn’t an option, but it turns out that one can get quite a lot done with floor area barely larger than a sheet of plywood.

I designed a Paulk-style workbench top, cut it out on my friend’s CNC, and mounted it all on screwed-together 2x4 legs:

So far I’ve mostly worked with cheap plywood from Hornbach, using the following tools:

The workbench has MFT-style 20mm “dog holes” on a 96mm grid, which allows for all sorts of useful accessories.

For example: I purchased Hooked on Wood’s bench dog rail hinges, which makes it easy to flip the track up/down to slide wood underneath to make cross cuts:

The $10 dog hole clamp on the right holds a stop block, which allows me to make repeated cuts.

Since the dog holes were cut with a CNC and the rail is straight, square cuts can be made by:

  1. making a known straight cut with the track saw on its track (whether on the workbench or outside on sawhorses)
  2. pushing this reference edge up against the two bench dogs on the top
  3. cutting along the track

See Bent’s Woodworking for more detail on this process.

While I wish I had space for a full size sliding table saw and/or CNC, this workbench and track saw seems like a decent backyard shed solution.

LED lighting

Last winter I decided to fight the gloomy Dutch weather by buying a bunch of high-CRI LEDs to flood my desk with artificial daylight:

See the build log for more details.

This lighting has worked out swimmingly — it helps me wake up in the morning and makes the whole space feel nice even on the grayest rainy day.

After sundown, my computer switches to “dark mode” colors and I switch the room to cozier warm-white LEDs.

I had about 8 meters of LED strip leftover, which I used with LED diffuser profiles to illuminate my workshop.

Euroboxes

When we moved into our new (completely unfurnished) apartment over the summer, I was adamant I’d build all of the furniture we needed. However, sightly storage solutions have taken longer than anticipated, so to eliminate the immediate clutter I purchased a bunch of 600x400x75mm euroboxes:

At $4/each (used), they’re an absolute bargain.

Since they’re plastic, they slide great on waxed wood rails and make perfect lil’ utility drawers. The constraint of needing to use fixed size drawers makes it easier for me to design the rest of a furniture piece around them.

For example, just take a brad nailer to the limitless amounts of discarded particle board available on the streets of Amsterdam, and boom, one-day-build 3d-printer cart in the meter closet:

Or, throw some drawers in the hidden side of these living room plywood coffee table / bench / scooters:

Now we have a tidy place to hide the TV remote and wireless keyboard/mouse, coffee table books, store extra blankets, etc.

Ikea Skadis coffee/smoothie station

Our kitchen only has 1.6 m2 (17 ft2) of counter space, so we mounted two Ikea Skadis pegboards to the side of our fridge to make a coffee / smoothie station:

The clear Ikea containers are great for nuts and coffee since you can grab them with one hand and drop ‘em in the blender or grinder.

I designed and 3d-printed custom mounts for my Clever Dripper, coffee grinder (1Zpresso k-series), little water spritzer, and bottles of Friedhats beans.

Since we can’t screw into the fridge, the panels are hanging from some 3d-printed hooks command stripped on the top of the fridge cabinet. Clear nano-tape keeps the Skadis boards from swinging.

The cheap Ninja cup blender is quite loud, so we leave a pair of Peltor X4 ear defenders hanging next to it.

Ikea Maximera drawers

As soon as we made the smoothie station we decided to replace the cabinet shelves underneath it with drawers. (The only drawers that came with the kitchen were installed underneath the range, creating constant conflict between the cook and anyone needing silverware.)

Decent soft-close undermount drawer slides from Blum/Hettich cost like $30 each, and for the same price Ikea sells slides with a drawer box attached.

Since we’re renting and can’t make permanent changes to the kitchen, I built a carcass for the drawers within the existing cabinet:

The particle board sides carry the weight of the drawers to the base of the existing cabinet, and they’re fixed to the walls with nano-tape rather than screws.

Nicki 3d-printed cute pulls and we threw those onto temporary fronts made of leftover MDF. As you can see from the hardware poking through, these 8mm fronts are a bit too thin, so I plan to replace them with thicker MDF, probably sculpted with a goofy pattern in the style of Arno Hoogland.

Having drawers is awesome:

We bought a bunch of extra cups for the Ninja blender and keep them pre-filled with creatine and protein powder. The bottom drawer holds the dozen varieties of peanut butter remaining from the Gwern-inspired tasting I held in November. (The UK’s Pip & Nut peanut butters were the crowd favorites, by the way.)

Digital

Emacs and LLMs

I’ve used Emacs for something like 15 years, but after the first year or so I deliberately avoided trying to customize it, as that felt like too much of a distraction from the more important yaks I was shaving through my 20’s and early 30’s.

However, in early 2025 I decided to dive in, for two reasons:

  1. I ran across Prot’s video demonstrating a cohesive set of well-designed search and completion packages, which suggested to me that there were interesting ideas being developed in the “modern” Emacs community
  2. I discovered gptel, which makes it extremely easy to query large language models within Emacs — just highlight text, invoke gtpel, and the response is inserted right there.

What’s special about Emacs compared to other text editors is that it’s extremely easy to customize. Rather than a “text editor”, Emacs is better thought of as an operating system and live programming environment which just so happens to have a lot of functions related to editing text.

My day-to-day coding, writing, and thinking environment within Emacs has improved tremendously in 2025, as every time I’ve had any sort of customization or workflow-improvement idea, I’ve been able to try it out in just a minute or two by having an LLM generate the necessary Emacs Lisp code.

My mentality changed to “yeah, I’m sure it’s possible but I don’t have time or interest to figure out how to do it with this archaic and quirky programming language” to “let me spend two minutes trying”.

Turns out there’s a lot of little improvements that can be done by an LLM in few minutes. Here are some examples:

Emacs has a pretty smooth gradient between “adjust a keybinding”, to “quick helper function”, to a full on workflow. Here’s an example from the latter end of that spectrum.

I asked Claude Code to make some minor CSS modifications for a project, then got nerd-sniped trying to understand why it used a million tokens to explore my 4000-word codebase and edit a dozen lines:

Usage by model:
        claude-haiku:  8.6k input, 5.4k output, 434.2k cache read, 33.4k cache write ($0.1207)
       claude-sonnet:  1.0k input, 262 output, 0 cache read, 0 cache write ($0.0069)
     claude-opus-4-5:  214 input, 8.3k output, 842.5k cache read, 47.8k cache write ($0.93)

After a bit of digging, it seemed likely this is a combination of factors:

For comparison, I invoked Opus 4.5 manually with all of my source code and asked what I needed to change, and it nailed the answer using only 5000 tokens (4500 input, 500 output).

So I leaned into this and wrote my own lightweight, single-shot workflow in Emacs:

I’ve used it a handful of times so far and it works exactly the way I’d imagined — it’s much faster than waiting for an “agent” to make a dozen tool calls and lets me take advantage of LLMs for tedious work while remaining in the loop.

(Admittedly, this one took a few hours rather than a few minutes, but it was well worth it in terms of getting some hands-on experience building a structured LLM-based workflow.)

A little Photos.app exporter

When you copy images out of Photos.app, it only puts a 1024 pixel wide “preview image” on the pasteboard. This loses too much detail.

The built-in “export” workflow is tedious to use and doesn’t actually compress well, so you have to do another pass through Squoosh or ImageOptim anyway. Of course, you’ll want to resize before you do that, maybe in Preview?

I noticed how annoyed I was trying to add photos to my articles, so I vibe-coded a little Photos.app exporter that behaves exactly like how I want.

UV (Python dependencies)

I haven’t done much Python in my career, but it’s a popular language that I’d occasionally need to tap into to use some specific library (e.g., OpenCV, NumPy, JAX) or run the code behind some interesting research paper.

The package management has always been (from my perspective of a casual outsider) an absolute mess. Yes, with lots of good reasons related to packaging native code across different operating systems and architectures, etc. etc. etc.

Whatever, if pip install failed to build my eggs or wheels or whatever, I’d usually just give up.

As for reproducibility and pinning to exact versions…¯\_(ツ)_/¯.

“Maybe if I do nothing the problem will fix itself” isn’t a great problem solving strategy, but it definitely worked out for me for understanding Python dependency managers: I came across UV in late 2024 and it…just works? It’s also fast!

I can now finally create a Python project, specify some dependencies, and automatically get a lockfile ensuring it’ll will work just fine on my other computer, 6 months from now!

This problem has been a thorn in the side of not just software developers, but also scientific researchers for decades. The folks who’ve finally resolved it deserve, like, the Nobel Peace prize.

Mise-en-place (all dependencies)

This past year I’ve also been loving mise-en-place. From their homepage:

mise is a tool that manages installations of programming language runtimes and other tools for local development. For example, it can be used to manage multiple versions of Node.js, Python, Ruby, Go, etc. on the same machine.

Once activated, mise can automatically switch between different versions of tools based on the directory you’re in. This means that if you have a project that requires Node.js 18 and another that requires Node.js 22, mise will automatically switch between them as you move between the two projects.

I’ve used language-specific versions of this idea, and it’s been refreshing to throw all of those out in favor of a single uniform, fast solution.

I have a user-wide “default” config, containing stuff like:

and on specific projects I specify the same and additional tools, so that collaborators can have a “single install” that guarantees we’re all on the same versions of everything.

Sure something like Nix with hermetically sealed, content addressed, etc., etc. is better in theory, but the UX and conceptual model is a mess.

Mise feels like a strong, relatively simple local optimum: You specify what you want through a simple hierarchy of configs, mise generates lockfiles, downloads the requested dependencies, and puts them on the $PATH based on where you are.

I’ve been using it for a year and haven’t had to learn anything beyond what I did in the first 15 minutes. It works.

Atuin (shell history)

Atuin records all of your shell commands, (optionally) syncs them across multiple computers, and makes it easy to recall commands with a fuzzy finder. It’s all self-hostable and is distributed as a single binary.

I find the shell history extremely useful, both for remembering infrequently used commands, as well as for simply avoiding typing out tediously long ones with many flags. Having a proper fuzzy search that shows a dozens of results (rather than just one at a time) makes it straightforward to use.

Before this I wouldn’t have thought twice about my shell command history, and now it’s something I deliberately back up because it’s so useful.

YouTube Premium

At some point in 2025 the ad-blocker I was using stopped working on YouTube and I started seeing either pauses or (uggghhh) commercials (in Dutch, which Google must think I understand, despite 15 years of English GMail, not to mention my Accept-Language header).

Given that YouTube is a Wonder of the World and a $20/month leaves me with a consumer surplus in the neighborhood of $104–105, I decided to subscribe to YouTube Premium.

Honestly I just wanted the ads to stop, but it’s even better — I can conveniently download videos to my phone, which means I can watch interesting videos while riding on the stationary exercise bike in the park near my house.

It also comes with YouTube Music, which immediately played me a late 00’s indie rock playlist that brought me back to college.

100% worth it.

FlowStorm (Clojure debugger)

I don’t normally use debuggers, especially since in Clojure it’s usually straightforward to pretty-print the entire application state.

However, this usual approach failed me when I was building an interpreter for some CAD programming language experiments — each AST node holds a reference to its environment (a huge map), and simply printing a tree yields megabytes of text.

FlowStorm takes advantage of the fact that idiomatic Clojure uses immutable data structures — the debugger simply holds a reference to every value generated during a computation, so that you can analyze them later.

There are facilites to search all of the recorded values. So if you a see a string “foo” on your rendered webpage or whatever, you can easily answer questions like “where is the first callstack where the string ‘foo’ shows up?”.

All of the recorded data is available programmatically too. I used this infrastructure to make a live visualization of a 2D graphics program where as you move your cursor around the program source code, you see the closest graphical entity rendered automatically.

(“A debounced callback triggered by cursor movement which executes Clojure code and highlights text according to the return value” is another example of an Emacs customization I never would have attempted prior to LLMs.)

Whispertron (transcription)

I vibe-coded my own lil’ voice transcription app back in October 2024, but I’m including it in this list because using it has become second-nature to me in 2025.

Before I had reliable transcription at my fingertips, I never felt hindered by my typing speed (~125 words per minute). However, now that I have it, I find that I’m expressing much more when I’m dictating compared to typing.

It reminds me of the difference between responding to an email on an iPhone versus using a computer with a large monitor and full keyboard. I find myself providing much more context and otherwise elaborating my thoughts in more detail. It’s just easier to speak out loud than type out the same information.

This yields much better results when prompting LLMs: typing, I’ll say “do X”; speaking, I’ll say “do X, maybe try A, B, C, remember about Y and Z constraints”.

It also yields better relationships: When emailing and texting friends, I’ll dictate (and then clean up / format) much more detailed, longer responses than what I’d type.

Misc. stuff