For a while I have been running a self-hosted n8n on my office NUC, a Geekom IT12 with plenty of CPU and RAM. However, I tinker with it from time to time. And, inevitably, I (or Claude) break something, and then I have to wait until the next morning to reboot it when I arrive at my office. So I decided to move it to a spare Raspberry Pi 4B I had collecting dust in my closet. That way, instead of having to pause whatever I was working on wait until the next day, I could just walk over and pull the plug when things went sideways.
Since I'm now using NixOS, I figured the move would be straightforward. Just move a few flakes around, switch from x86_64 to aarch64, and we're laughing. The reality was not quite as smooth. The first build overheated and shut off the Pi (a 20€ fan case from Amazon fixed that). The second build got further, but then the kernel OOM killer terminated it. The build had eaten through all 8GB of RAM, and since NixOS doesn't configure any swap by default, there was nowhere for the overflow to go.
Swap has been the standard way to deal with memory exhaustion since I first started using Linux 30-odd years ago. But staring at the logs, I found myself wondering: why do I never have to think about this on my Mac or my Windows machine? Both of those handle memory pressure gracefully, even on 8GB machines. Something was happening behind the scenes on those OSes that wasn't happening on NixOS.
In this article, I'll walk through what that "something" is, and show the three NixOS options (plus one n8n-specific overlay) that turned my Pi from a crash-prone headless server into one that can survive heavy builds without intervention.
Claude Code is fantastic when you're sitting at the computer it's running on. You hand it a task, watch it work, course-correct when it goes sideways. The trouble starts when you want it to keep going while you're out, asleep, or otherwise away from the keyboard.
One approach is to stop your machine from sleeping in the first place. macOS has caffeinate, and Linux has half a dozen ways to inhibit suspend. That works for short jobs, but it ties up your main machine and burns your battery if you're on a laptop.
A nicer approach is to give Claude Code its own box. A spare Mac Mini, a NUC tucked into a closet, even a Raspberry Pi will do. You just need something that's always on and doesn't care if you wander off. Since Claude Code is a CLI, you SSH in from wherever you are and use it like any other terminal app. It works great. Right up until the moment your SSH connection drops, which it inevitably will, because that's what SSH connections do. When the connection goes, Claude Code goes with it, and whatever it was halfway through doing is gone.
This problem gets especially fun if you're driving Claude Code from your phone over a client like Termius, where a flaky cellular connection or a screen lock can cut you off in the middle of an interesting tool call.
I had a Kindle Voyage collecting dust in a drawer. It's one of the nicest e-readers Amazon ever made (flush glass screen, page turn buttons) but I barely use it anymore as I prefer paper books now. It always bothers me when I have unused tech, and I remembered an article by Matthew Petroff where he jailbroke his Kindle and turned it into a weather display. I wanted to do the same: an always-on weather station that sits in my kitchen near my coffeemaker so I can see the forecast in the morning. It also seemed like a good project to try using Claude Code as an assistant, since it involves a lot of SSH, shell scripting, and reading other people's code.
In this article, I will walk through how I jailbroke the Voyage, got a standalone weather display working with automatic sleep/wake cycles, and the many dead ends I hit along the way.
I recently needed to run sudo commands through Claude Code on Linux, but ran into a problem: Claude Code's Bash tool isn't interactive, so there's no way to type a password or scan a fingerprint when sudo prompts for authentication.
Using Process.st just became even easier, thanks to our new Yammer integration. Since the general procedure for integrating with Yammer should be similar for most SaaS apps, I made a public template of the process.
Why not harness the power of Play and Scala and write our own Writeable to do that job? Heck, we already have a MultipartFormData object for handling multipart form requests, why not use that?
I recently needed to add a DateTime picker to Process Street for use with our upcoming assignment feature. I ended up choosing eonasdan's DateTime picker. Here's the code to wrap it in an AngularJS directive.
In the next update of Process Street we are adding more caching to our front end JavaScript client (named Front Street after the street in Toronto) in an effort to make the experience of using our app as fast as possible.
Front Street uses web storage (specifically localStorage) to store persistent user data. To make the cache as effective as possible, it should be able to grow to use as much space as it can. However, we also store other information in localStorage, like user session information (the user's login token and list of teams, for example). That means if the cache grew to use all the localStorage space, the app couldn't function properly. Thus, we needed a way to detect the size of localStorage so we could partition localStorage between cache and session information.
Unlike Process Street, MailTheme will be running on Google Cloud and, for the time being, won't be behind a load balancer or proxy. As such, I needed to make all HTTP requests auto-redirect to HTTPS via Play. This turned out to be more difficult than I first imagined, as Play prior to version 2.3 has no way to detect whether or not the incoming request is over SSL.