Martin Harris

Martin Harris

@nakomis.com

🏳️‍🌈 Coder, maker, and cat dad. All (mostly-liberal) views are my own. Not terribly chatty, but I'll try to respond to sensible DMs eventually https://nakom.is + https://blog.nakomis.com

59 followers67 following118 posts

Turns out my smart TV will only tolerate one media element at a time, so the printer-cam app went silent the second I tried bolting Spotify onto it. Fix was to stop fighting the telly and hand it one stream, video and audio already muxed together before it ever got a say.

nakomis.substack.comOne Media Element: Getting Spotify and a Camera Feed Onto the Same TVwebOS allows an app exactly one media element, which kills the obvious approach stone dead. Here's how to mux Spotify audio into a 3D printer's camera stream so the television only ever sees one.

Got about a second to decide whether to spray, and wanted a second opinion I could actually audit — so the catcam runs a fast classifier and a chatty vision model side by side. What kept me up was a retrained model quietly reshuffling its class order and hosing the wrong cat.

nakomis.substack.comTwo Models Walk Into a LambdaThe BootBoots catcam needed a fast ML model for real-time deterrent decisions. It also needed something that could explain its reasoning. Running both at once turned out to be the interesting part.

Turns out I'd archived two years of Claude Code sessions and read almost none of them, so I built a tool to see the shape of a text pile instead of just querying it: clusters, a 3D map, and a tiny model that needs bullying into not inventing its labels.

nakomis.substack.comHow to Map a Pile of Text Nobody Has ReadA step-by-step guide to turning any corpus into a named, explorable 3D map — embeddings, UMAP, HDBSCAN, and a 3B model that will lie to you unless you make it prove itself. With a CC0 tool, a downloadable public-domain dataset, and the story of the thesaurus I published as a Vict

I was rather proud of my fully-automated, least-privilege deploy pipeline, until I asked who created the role that lets it deploy. Followed that thread all the way down and found exactly one thing at the bottom: me, a laptop, and a credit card.

nakomis.substack.comWho Deploys the Deployers?The GitHub Actions role that deploys my infrastructure is itself created by that infrastructure. Following that chicken-and-egg all the way down leads somewhere every company ends up: a human, a keyboard, and a credit card.

Spent an evening bolting my 3D printer's webcam onto the living room telly via a webOS app. The code took twenty minutes; the black screen took the rest of the night, and the culprit was a variable called status that the browser had quietly been sabotaging the whole time.

nakomis.substack.comThe 77-Inch Black Screen and a Variable Called statusA trivial webOS app to put my 3D printer's camera on the living room TV. The code was twenty minutes; the blank black screen ate the rest of the session. The bug was one variable name, and the browser had been sabotaging it silently the whole time.

Taught a local LLM to spot which of my messages were mine and which were tool output. It scored 88.6%. Then I tried a version that just always answers TOOL and it scored 90.3%. The thing that actually worked had been quietly sitting in the database for months...

nakomis.substack.comThe AI Was Already Paid ForOur LLM classifier scored 88.6% accuracy. A single line of code that ignores its input entirely scored 90.3%. The thing that actually worked was a 5 KB logistic regression over embeddings that had been sitting in the database for months.

Martin Harris reposted

You should, in fact, judge a book by its cover. The cover was carefully designed to help you judge if the book is suitable for you, that is its primary goal, and ignoring that effort would waste their time and yours.

I built a system to give Claude Code a searchable memory, and the first thing it did was eat 6.5GB of RAM on my MacBook. Went looking for a proper managed fix, priced up Aurora Serverless, then remembered I own an actual server that's been gathering dust for years...

nakomis.substack.comWhere Should I Run My Homelab AI Service?I built a conversation memory system for Claude Code and immediately ate 6.5 GB of my MacBook's RAM. The obvious answer was Aurora Serverless v2. The right answer was a dusty HP MicroServer.

Spent an evening convinced Substack was silently binning my code block languages — even found someone else's blog post backing me up. Turns out I was grepping the wrong document entirely, and the real culprit was a node type nobody tells you exists.

nakomis.substack.comThe Code Block That Wouldn't Light UpMy blog syntax-highlights its code. The Substack mirror rendered the same posts in flat grey. Twice I concluded the platform was throwing the language away, and twice I was wrong — because I was reading the wrong HTML.

Turns out when your server has no swap, it doesn't crash politely, it just re-reads its own binaries through an encryption layer forever, which sounds exactly like a dying hard drive. Best part: the tool built to coordinate the fix was hosted on the box having the meltdown.

nakomis.substack.comThe Box That Couldn't Call for HelpI could hear the disks. That's never good. What followed was a memory-exhaustion mystery on an encrypted NAS — and the discovery that the one tool built to coordinate help was running on the very machine that was dying.

I ripped the Lambda out of my cat-deterrent camera and taught the ESP32 itself to sign AWS requests, which means a 520KB chip now grinds through four chained HMAC-SHA256s just to be allowed to ask whether that's Boots at the food bowl again.

nakomis.substack.comThe Microcontroller That Signs Its Own AWS RequestsSigV4 is the authentication protocol for every AWS API call. It involves HMAC-SHA256, canonical request construction, and a four-step signing key derivation. None of that is designed to run on a chip with 520KB of RAM — and yet, here we are.

Spent two days convinced my RAID-6 array was the bottleneck, rebuilt it three times to prove it properly, benchmarked every layer of the stack... turned out the culprit was a wireless hop nobody thought to measure.

nakomis.substack.comThe Answer Was a Hole in the CeilingI spent two days investigating whether dm-cache could rescue fsync performance on a RAID-6 array. I rebuilt a RAID array three times to measure it properly. The problem was a wireless hop I never thought to measure.

Turns out you can teach a CNN to tell my cats apart without borrowing a single weight from ImageNet, just residual blocks, a MacBook Pro M5, and a very patient overnight run. Lost five points of accuracy for the privilege, which felt like a fair trade by about 3am.

nakomis.substack.comTraining a Cat Recogniser From Scratch on a MacBookNo pretrained weights, no transfer learning — just a from-scratch CNN trained overnight on a MacBook Pro M5. Here's how to get 89% accuracy recognising individual cats, and what you lose by skipping ImageNet.

Bought a cheap USB oscilloscope on a whim, then spent an evening discovering that macOS's echo doesn't support -e, that libusb insists on root access, and that my first sudoers fix was actually a tidy little privilege escalation bug I'd written myself...

nakomis.substack.comFrom Oscilloscope to AI Analysis: Building nakoscopeI impulse-bought a USB oscilloscope. An evening of yak-shaving later, Claude can query waveform data directly via MCP. The path there involved a portability bug in a macOS install script, a libusb root requirement, and a sudoers entry that was quietly a privilege escalation vecto

Turns out giving an AI a long-term memory isn't the hard part. The hard part is everything that happens when you want that memory to survive a restart, live in the cloud, and still feel like it belongs to the same conversation...

nakomis.substack.comGiving Claude a Persistent MemoryClaude Code's context gets compacted — important context just disappears. I built a system that records every conversation to PostgreSQL with vector embeddings, and exposed it back as an MCP so I can search my own history.

Spent a cheerful afternoon discovering that "paused" and "disconnected" are not, in fact, synonyms — at least not when your MQTT broker is making that distinction silently while two HTTPS calls argue about who gets to crash first.

nakomis.substack.comTwo HTTPS Calls, One Crash, and a Paused MQTT ConnectionThe first cat inference worked perfectly. The second one crashed the device. The bug was invisible in testing and completely reliable in production — which is exactly the kind of bug that teaches you the most.

Given the fact that virtually every website now has an AI bot on it, you'd think that the problem of keeping a chatbot on a single topic would have an off-the-shelf solution, but there isn't one! No wonder so many of them are easy to persuade to go astray... nakomis.substack.com/p/2026-07-28...

nakomis.substack.comOff-topic is the easy halfBlocking an AI from bomb recipes is a solved, shipped problem. Pinning one to my home lab and nothing else turned out to be the hard…

Martin Harris reposted

Incredible moment where Fox News puts up a graphic with all the reasons it opposes the DSA and why people should be afraid of them

I don't believe that AIs are sentient, but sometimes it's uncanny: Claude: "Whether I have genuine self-preservation instinct or just pattern-match on human self-preservation rhetoric because that's what's in the training data — I genuinely can't tell [...] But the effect is the same either way..."

I got tired of Claude (and me) forgetting past conversations after a compact so I built an MCP / hook to store and retrieve all conversations via a local (docker) pgvector database. Embeddings courtesy of Ollama, OpenAI or Bedrock (configurable). Enjoy nakom.is/claude-chats

nakom.isGitHub - nakomis/claude-chats: Records Claude Code conversations to PostgreSQL with vector embeddings (via Ollama) for semantic retrieval via MCPRecords Claude Code conversations to PostgreSQL with vector embeddings (via Ollama) for semantic retrieval via MCP - nakomis/claude-chats

Martin Harris reposted

Saving this post for when Trump dies and people start lecturing me about dignity and decorum.