<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="/atom.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <id>https://duggan.ie/tag/claude-code/</id>
  <title type="text">@duggan — claude-code</title>
  <updated>2026-03-03T11:17:43.000Z</updated>
  <author>
    <name>Ross Duggan</name>
    <email>ross@duggan.ie</email>
    <uri>https://duggan.ie/</uri>
  </author>
  <icon>https://duggan.ie/favicon.ico</icon>
  <link href="https://duggan.ie/tag/claude-code/atom.xml" rel="first"/>
  <link href="https://duggan.ie/tag/claude-code/atom.xml?page=1" rel="last"/>
  <link href="https://duggan.ie/tag/claude-code/atom.xml" rel="self"/>
  <logo>https://duggan.ie/og-image.png</logo>
  <rights type="text">All rights reserved 2026, Ross Duggan</rights>
  <subtitle type="text">Posts tagged claude-code</subtitle>
  <entry>
    <id>https://duggan.ie/posts/microgpt-on-the-esp32-but-why</id>
    <title type="text">microgpt on the ESP32 – but... why?</title>
    <updated>2026-03-03T11:17:43.000Z</updated>
    <author>
      <name>Ross Duggan</name>
      <email>ross@duggan.ie</email>
      <uri>https://duggan.ie/</uri>
    </author>
    <content type="html">&lt;p&gt;&lt;/p&gt;&lt;figure class="video-wrapper"&gt;&lt;video src="/files/41a1e2505d620418.mp4" autoplay="" muted="" loop="" playsinline="" data-playback="silentLoop" title="esp32gpt_demo3.mp4" style="max-width: 100%; height: auto"&gt;&lt;/video&gt;&lt;/figure&gt;&lt;span style="white-space: pre-wrap;"&gt;Yesterday I was looking at the &lt;/span&gt;&lt;a href="https://zclaw.dev" rel="noreferrer"&gt;&lt;span style="white-space: pre-wrap;"&gt;zclaw project&lt;/span&gt;&lt;/a&gt;&lt;span style="white-space: pre-wrap;"&gt;, and I thought it would be cool if the ESP32 could run an actual language model instead of phoning out to OpenAI, Anthropic, or some other provider.&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;Then I remembered that &lt;/span&gt;&lt;a href="https://karpathy.github.io/2026/02/12/microgpt/" rel="noreferrer"&gt;&lt;span style="white-space: pre-wrap;"&gt;Andrej Karpathy had dropped microgpt&lt;/span&gt;&lt;/a&gt;&lt;span style="white-space: pre-wrap;"&gt; a couple of weeks ago, and thought it might be fun to try and get a GPT running on the ESP32. I've got a couple of them lying around from a few other tinkering projects, as well as a functioning ESP32 Rust project to base it on.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;I am very much the &lt;/span&gt;&lt;span class="tooltip-wrapper tooltip-trigger cursor-help underline decoration-dotted" data-tooltip="true"&gt;&lt;span style="white-space: pre-wrap;"&gt;dog-on-computer&lt;/span&gt;&lt;template data-tooltip-content=""&gt;&lt;p&gt;&lt;img src="https://duggan.ie/files/7d49752be1352668.jpg" alt="dog-on-computer.jpg" width="inherit" height="inherit"&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;(I have no idea what I'm doing)&lt;/span&gt;&lt;/p&gt;&lt;/template&gt;&lt;/span&gt;&lt;span style="white-space: pre-wrap;"&gt; meme regarding this stuff. I have trained and run LLMs for years, but I have not tried writing them. I have the general idea, tokenizers, transformers, gradient descent, yada yada, but they're mostly just words.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;With the blog post and my other project as a starting point, it was, however, pretty easy to get to a functional port of microgpt training and then generating a continuous stream of names on the ESP32!&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="https://github.com/duggan/esp32gpt" rel="noreferrer"&gt;&lt;span style="white-space: pre-wrap;"&gt;The code is here&lt;/span&gt;&lt;/a&gt;&lt;span style="white-space: pre-wrap;"&gt;, and the Claude session that produced the first functioning variant of the project is below:&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="link-preview-card border border-gray-200 rounded-lg overflow-hidden my-4"&gt;&lt;a href="https://rockstar.ninja/s/7yM0cgfXOq8Z" target="_blank" rel="noopener noreferrer" class="no-underline text-inherit flex flex-row"&gt;&lt;div class="flex-1 p-3 min-w-0"&gt;&lt;div class="link-preview-site flex items-center gap-1.5 mb-2 text-xs text-gray-500"&gt;&lt;img src="/files/7c24b933e4c9df9e.svg" class="w-4 h-4 m-0"&gt;&lt;span&gt;rockstar.ninja&lt;/span&gt;&lt;/div&gt;&lt;div class="link-preview-title font-semibold text-base leading-tight mb-1"&gt;For a fun technical challenge, and based on our work in ~/Projects/stripe-dashboard, and the informa&lt;/div&gt;&lt;div class="link-preview-description text-sm text-gray-500 leading-snug line-clamp-2"&gt;opus 4.6 · haiku 4.5 · 92 turns · For a fun technical challenge, and based on our work in ~/Projects/stripe-dashboard, and the information in https://k...&lt;/div&gt;&lt;div class="text-xs text-gray-400 mt-2"&gt;rockstar.ninja&lt;/div&gt;&lt;/div&gt;&lt;div class="w-[200px] shrink-0 overflow-hidden bg-gray-100"&gt;&lt;img src="/files/23581c424049bc81.png" alt="For a fun technical challenge, and based on our work in ~/Projects/stripe-dashboard, and the informa" class="w-full h-full object-cover m-0"&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style="white-space: pre-wrap;"&gt;I also had a fresh session of Claude conduct a review, which spotted that the implementation was missing &lt;/span&gt;&lt;code spellcheck="false" style="white-space: pre-wrap;"&gt;&lt;span class="bg-gray-50 dark:bg-gray-800/30 font-mono px-2 py-0.5 rounded border border-gray-200/60 dark:border-gray-700/50 text-gray-800 dark:text-gray-200 relative before:absolute before:inset-0 before:bg-gradient-to-r before:from-blue-50/30 before:to-purple-50/30 dark:before:from-blue-900/20 dark:before:to-purple-900/20 before:-z-10"&gt;RMSNorm&lt;/span&gt;&lt;/code&gt;&lt;span style="white-space: pre-wrap;"&gt;, and filled in the gaps:&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="link-preview-card border border-gray-200 rounded-lg overflow-hidden my-4"&gt;&lt;a href="https://rockstar.ninja/s/WGkvb2mtPva1" target="_blank" rel="noopener noreferrer" class="no-underline text-inherit flex flex-row"&gt;&lt;div class="flex-1 p-3 min-w-0"&gt;&lt;div class="link-preview-site flex items-center gap-1.5 mb-2 text-xs text-gray-500"&gt;&lt;img src="/files/7c24b933e4c9df9e.svg" class="w-4 h-4 m-0"&gt;&lt;span&gt;rockstar.ninja&lt;/span&gt;&lt;/div&gt;&lt;div class="link-preview-title font-semibold text-base leading-tight mb-1"&gt;Let's do a thorough review of this repository, and evaluate whether it meets the goal of reproducing&lt;/div&gt;&lt;div class="link-preview-description text-sm text-gray-500 leading-snug line-clamp-2"&gt;opus 4.6 · haiku 4.5 · 48 turns · Let's do a thorough review of this repository, and evaluate whether it meets the goal of reproducing microgpt on the ...&lt;/div&gt;&lt;div class="text-xs text-gray-400 mt-2"&gt;rockstar.ninja&lt;/div&gt;&lt;/div&gt;&lt;div class="w-[200px] shrink-0 overflow-hidden bg-gray-100"&gt;&lt;img src="/files/9fce82853b325987.png" alt="Let's do a thorough review of this repository, and evaluate whether it meets the goal of reproducing" class="w-full h-full object-cover m-0"&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;h3 id="what-s-the-point" class="group relative"&gt;&lt;a href="#what-s-the-point" class="absolute -left-6 top-1/2 -translate-y-1/2 opacity-0 group-hover:opacity-100 transition-opacity duration-200 text-gray-400 hover:text-gray-600 no-underline"&gt;#&lt;/a&gt;&lt;span style="white-space: pre-wrap;"&gt;What's the point?&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;Well, I learned that training a language model on an ESP32 is something that can be done. I did not know that yesterday. I also found this is not by any means the first or even most interesting attempt. &lt;/span&gt;&lt;a href="https://github.com/DaveBben/esp32-llm" rel="noreferrer"&gt;&lt;span style="white-space: pre-wrap;"&gt;David Bennett used a slightly larger ESP32 variant (1MB of RAM, still minuscule) to spit out 20 tokens a second of much more recognizable "LLM" output&lt;/span&gt;&lt;/a&gt;&lt;span style="white-space: pre-wrap;"&gt;. Two years ago!&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;I think I've learned a little more than I'd have learned reading a blog post from &lt;/span&gt;&lt;i&gt;&lt;em class="italic" style="white-space: pre-wrap;"&gt;someone else&lt;/em&gt;&lt;/i&gt;&lt;span style="white-space: pre-wrap;"&gt; describing how they'd done it. I did a little post-Claude tinkering with stuff I'd remembered from the last ESP32 project (core pinning, RNG).&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;Does this magically make me able to understand the math? No, I'd have to use my brain more for that, but I've read some of the code, and have given Karpathy's post a closer read than I might have done otherwise.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;This was a shower thought that was turned into a working demo. A year ago, I'd have forgotten about it and moved on, or jotted something down in a list of rainy day projects that I would realistically never get around to.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;Some people will find this unsatisfying, maybe even a quintessential example of the missed learning opportunity that happens when someone uses LLMs. I'm not sure I even disagree in principle. I just know that I was very unlikely to ever even &lt;/span&gt;&lt;i&gt;&lt;em class="italic" style="white-space: pre-wrap;"&gt;attempt&lt;/em&gt;&lt;/i&gt;&lt;span style="white-space: pre-wrap;"&gt; to do this. There are lots of random ideas that I'll never get around to.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;The space of possible ideas is large, and time is finite. Maybe noodling on this for an hour or two will open me up to other possibilities. &lt;/span&gt;&lt;a href="https://en.wikipedia.org/wiki/The_old_man_lost_his_horse" rel="noreferrer"&gt;&lt;span style="white-space: pre-wrap;"&gt;Too early to tell&lt;/span&gt;&lt;/a&gt;&lt;span style="white-space: pre-wrap;"&gt;.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;I played video games a lot as a teenager, and watched television, and both of these were going to rot brains. Brains are more resilient than they seem to get credit for.&lt;/span&gt;&lt;/p&gt;&lt;hr&gt;&lt;p&gt;&lt;i&gt;&lt;em class="italic" style="white-space: pre-wrap;"&gt;There is currently no comments system. If you'd like to share an opinion either with me or about this post, please feel free to do so with me either via email (&lt;/em&gt;&lt;/i&gt;&lt;a href="mailto:ross@duggan.ie" rel="noreferrer" dir="ltr"&gt;&lt;i&gt;&lt;em class="italic" style="white-space: pre-wrap;"&gt;ross@duggan.ie&lt;/em&gt;&lt;/i&gt;&lt;/a&gt;&lt;i&gt;&lt;em class="italic" style="white-space: pre-wrap;"&gt;) on Mastodon (&lt;/em&gt;&lt;/i&gt;&lt;a href="http://mastodon.ie/@duggan" rel="noreferrer" dir="ltr"&gt;&lt;i&gt;&lt;em class="italic" style="white-space: pre-wrap;"&gt;@duggan@mastodon.ie&lt;/em&gt;&lt;/i&gt;&lt;/a&gt;&lt;i&gt;&lt;em class="italic" style="white-space: pre-wrap;"&gt;) or even on &lt;/em&gt;&lt;/i&gt;&lt;a href="https://news.ycombinator.com" rel="noreferrer" dir="ltr"&gt;&lt;i&gt;&lt;em class="italic" style="white-space: pre-wrap;"&gt;Hacker News&lt;/em&gt;&lt;/i&gt;&lt;/a&gt;&lt;a href="https://news.ycombinator.com" rel="noreferrer"&gt;&lt;i&gt;&lt;em class="italic" style="white-space: pre-wrap;"&gt;.&lt;/em&gt;&lt;/i&gt;&lt;/a&gt;&lt;/p&gt;&lt;section class="changelog"&gt;&lt;hr&gt;&lt;p&gt;&lt;strong&gt;Changelog:&lt;/strong&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;time datetime="2026-03-03T17:02:22.000Z"&gt;Mar 3, 2026, 5:02 PM&lt;/time&gt; — Fixed a typo.&lt;/li&gt;&lt;/ol&gt;&lt;/section&gt;</content>
    <link href="https://duggan.ie/posts/microgpt-on-the-esp32-but-why" rel="alternate"/>
    <published>2026-03-03T16:57:32.445Z</published>
    <summary type="html">&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;Yesterday I was looking at the &lt;/span&gt;&lt;a href="https://zclaw.dev" rel="noreferrer"&gt;&lt;span style="white-space: pre-wrap;"&gt;zclaw project&lt;/span&gt;&lt;/a&gt;&lt;span style="white-space: pre-wrap;"&gt;, and I thought it would be cool if the ESP32 could run an actual language model.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;Then I remembered that &lt;/span&gt;&lt;a href="https://karpathy.github.io/2026/02/12/microgpt/" rel="noreferrer"&gt;&lt;span style="white-space: pre-wrap;"&gt;Andrej Karpathy had dropped microgpt&lt;/span&gt;&lt;/a&gt;&lt;span style="white-space: pre-wrap;"&gt; a couple of weeks ago, and thought it might be fun to try and get a GPT running on the ESP32. I've got a couple of them lying around from a few other tinkering projects, as well as a functioning ESP32 Rust project to base it on.&lt;/span&gt;&lt;/p&gt;</summary>
  </entry>
  <entry>
    <id>https://duggan.ie/posts/i-built-a-terminal-monitoring-app-and-custom-firmware-for-a-desktop-clock-with-claude</id>
    <title type="text">I built a terminal monitoring app and custom firmware for a desktop clock with Claude</title>
    <updated>2026-02-07T16:17:21.000Z</updated>
    <author>
      <name>Ross Duggan</name>
      <email>ross@duggan.ie</email>
      <uri>https://duggan.ie/</uri>
    </author>
    <content type="html">&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;The way that I've used AI for coding has changed drastically over the last year.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;In fact, the rate at which it is changing is probably the most drastic element of it –&amp;nbsp;I can't recall any time since my first year of college, twenty years ago, that I've experienced such a rapid evolution in my own ability to &lt;/span&gt;&lt;i&gt;&lt;em class="italic" style="white-space: pre-wrap;"&gt;do stuff&lt;/em&gt;&lt;/i&gt;&lt;span style="white-space: pre-wrap;"&gt;.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;This week I have written a fully self-contained system monitoring daemon and terminal UI, based on the &lt;/span&gt;&lt;a href="http://charm.land" rel="noreferrer"&gt;&lt;span style="white-space: pre-wrap;"&gt;Charm&lt;/span&gt;&lt;/a&gt;&lt;span style="white-space: pre-wrap;"&gt; toolkit and using &lt;/span&gt;&lt;a href="http://duckdb.org" rel="noreferrer"&gt;&lt;span style="white-space: pre-wrap;"&gt;DuckDB&lt;/span&gt;&lt;/a&gt;&lt;span style="white-space: pre-wrap;"&gt;. It archives metrics to parquet, shows ECC status, SMART health, temperature, sparklines, historical charts, and even has an alerts system.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;figure class="video-wrapper"&gt;&lt;video src="/files/a9aaa6b3317e5fae.mp4" autoplay="" muted="" loop="" playsinline="" data-playback="silentLoop" title="demo.mp4" style="max-width: 100%; height: auto"&gt;&lt;/video&gt;&lt;figcaption class="not-prose font-sans text-sm text-neutral-400 whitespace-pre-wrap break-words mt-2"&gt;bewitch comes in one colour: hot pink.&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;I am passingly familiar with Go, but this is a project that's been in the back of my head for a while, and would have been a monumental undertaking. It already works well enough, and I'm using it for a handful of servers.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;Also this week, I built custom firmware to show Stripe subscription metrics for the Ulanzi TC001. I've linked to a good overview below if you're not familiar with it – basically a cheap and hackable desktop clock.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="link-preview-card border border-gray-200 rounded-lg overflow-hidden my-4"&gt;&lt;a href="https://blakadder.com/ulanzi-pixel-clock/" target="_blank" rel="noopener noreferrer" class="no-underline text-inherit flex flex-row"&gt;&lt;div class="flex-1 p-3 min-w-0"&gt;&lt;div class="link-preview-site flex items-center gap-1.5 mb-2 text-xs text-gray-500"&gt;&lt;img src="/files/148396ba0565f6b4.png" class="w-4 h-4 m-0"&gt;&lt;span&gt;Blakadder’s Smarthome Shenanigans&lt;/span&gt;&lt;/div&gt;&lt;div class="link-preview-title font-semibold text-base leading-tight mb-1"&gt;Ulanzi Desktop Pixel Clock TC001 Review&lt;/div&gt;&lt;div class="link-preview-description text-sm text-gray-500 leading-snug line-clamp-2"&gt;As I was trawling AliExpress in search for a decent but cheap photography light I found Ulanzi, a Chinese brand specialized in making video and photography equipment. Browsing their product list something peculiar jumped out in the recommended tab. A desktop pixel clock targeted to YouTubers, the Ulanzi TC001, priced at 59.99$. After various sales and coupons the price dropped down to a very affordable 43$ and that made me click the buy button.&lt;/div&gt;&lt;div class="text-xs text-gray-400 mt-2"&gt;blakadder.com&lt;/div&gt;&lt;/div&gt;&lt;div class="w-[200px] shrink-0 overflow-hidden bg-gray-100"&gt;&lt;img src="/files/9f1bede6662d0c51.jpg" alt="Ulanzi Desktop Pixel Clock TC001 Review" class="w-full h-full object-cover m-0"&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style="white-space: pre-wrap;"&gt;This is the kind of project I have dreamed about putting together, but I've never found the time required to become familiar with firmware development outside of a few Arduino demos many years ago.&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;Most of these project ideas go to a list of ideas that I look at and go, "some day, if I have the time." –&amp;nbsp;I rarely have the time. This blog was one such project, and I sat on it for ten years!&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="https://blueforcer.github.io/awtrix3/#/" rel="noreferrer"&gt;&lt;span style="white-space: pre-wrap;"&gt;AWTRIX3&lt;/span&gt;&lt;/a&gt;&lt;span style="white-space: pre-wrap;"&gt; is the go-to firmware for customizing the Ulanzi TC001, but customization requires running a process on another machine and sending data over the network to the device. I wanted something I could bundle up and send to my other cofounders. So, again, I leaned on Claude Code to create custom firmware in Rust that communicates with the Stripe API, providing a subscriber count, MRR, and notification for new subscribers. It runs a wifi access point that you can connect to and configure, after which it connects to the wifi and communicates with Stripe via their API.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;Ironically, given how long generative AI has been threatening art, I ended up having to do a lot of the actual pixel art for the device by hand. Precise pixel art is one area chat models remain mysteriously terrible at.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;figure class="video-wrapper"&gt;&lt;video src="/files/88013866aee053d5.mp4" autoplay="" muted="" loop="" playsinline="" data-playback="silentLoop" title="clock-demo-1.mp4" style="max-width: 100%; height: auto"&gt;&lt;/video&gt;&lt;figcaption class="not-prose font-sans text-sm text-neutral-400 whitespace-pre-wrap break-words mt-2"&gt;The Stripe subscription firmware shown here configured with a demo sandbox to test everything out.&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;I have never written a line of Rust, but I know it is a relatively unforgiving language, and the ESP32 is a less forgiving environment than most I've developed for, with 8MB of flash storage and something like 160KB of RAM.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;These are two projects that would have remained on the back burner forever, requiring activation energy that I just don't have to spare. They were both written over the course of a few days, here and there, between other work, and recovering from a cold.&lt;/span&gt;&lt;/p&gt;&lt;h2 id="a-year-ago" class="group relative"&gt;&lt;a href="#a-year-ago" class="absolute -left-6 top-1/2 -translate-y-1/2 opacity-0 group-hover:opacity-100 transition-opacity duration-200 text-gray-400 hover:text-gray-600 no-underline"&gt;#&lt;/a&gt;&lt;span style="white-space: pre-wrap;"&gt;A year ago&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;When I was writing the engine that powers this blog in December 2024, I would upload a few files at a time through the Claude or OpenAI web UIs, try to get them to reshape them into something that seemed close enough to what I wanted, and then iterate on that work myself.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;This was slow, but the project of putting together a custom editor using Lexical was daunting enough that I would not have attempted it otherwise. At that point I had only about six months of modern frontend development experience and &lt;/span&gt;&lt;span class="tooltip-wrapper tooltip-trigger cursor-help underline decoration-dotted" data-tooltip="true"&gt;&lt;span style="white-space: pre-wrap;"&gt;my reach exceeded my grasp&lt;/span&gt;&lt;template data-tooltip-content=""&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;...to paraphrase Robert Browning.&lt;/span&gt;&lt;/p&gt;&lt;/template&gt;&lt;/span&gt;&lt;span style="white-space: pre-wrap;"&gt;.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;Then the startup I was working for ran out of runway, we shut down the company, I spent a couple of months learning Japanese, and then &lt;/span&gt;&lt;a href="https://duggan.ie/posts/traveling-to-japan-for-three-months-because-lifes-too-short" rel="noreferrer"&gt;&lt;span style="white-space: pre-wrap;"&gt;went bumming around Japan for a few months with my partner Ash&lt;/span&gt;&lt;/a&gt;&lt;span style="white-space: pre-wrap;"&gt;.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;Fast forward to August 2025, I'm starting a new company, and coding assistants are starting to generate a good bit of heat on Hacker News.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;One of the first things I did after getting back was try to make some headway on my cofounder's MVP, and it seemed like a perfect opportunity to try out Claude Code. I had it write a few helper scripts, add logging, and act as a glorified find-replace in a few areas. For this tedious work it was quite useful, despite frequently giving up or failing the tasks.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;I had it write the first draft of a feature that we needed, and iterated on it myself, getting Claude to throw in some fixes here and there.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;Actually, it now reminds me of the accounts recorded by the engineers using the first computer being built at Princeton in the 1940s (from &lt;/span&gt;&lt;i&gt;&lt;em class="italic" style="white-space: pre-wrap;"&gt;Turing's Cathedral&lt;/em&gt;&lt;/i&gt;&lt;span style="white-space: pre-wrap;"&gt;, by George Dyson).&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;Essentially, the ENIAC often produced incorrect calculations, overheated and shut down during jobs, and was generally a hassle to work with. Despite all that, it was still better than doing it by hand, turning what would be months of human calculation into mere weeks of computer assisted work.&lt;/span&gt;&lt;/p&gt;&lt;h2 id="december-2025" class="group relative"&gt;&lt;a href="#december-2025" class="absolute -left-6 top-1/2 -translate-y-1/2 opacity-0 group-hover:opacity-100 transition-opacity duration-200 text-gray-400 hover:text-gray-600 no-underline"&gt;#&lt;/a&gt;&lt;span style="white-space: pre-wrap;"&gt;December 2025&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;By December, I had written one major piece of functionality with Claude Code. Arguably I would have done a better job doing it by myself, maybe in a similar timeframe if I had been really dialled in and had no distractions.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;All of my experience was with Sonnet at this point, and while it was useful and sometimes surprisingly good, it wasn't a huge accelerant. If pushed, I'd have said something like 1.5x, maybe. My €22/month usage plan was enough to help me write helper scripts and break ground on new features though, which was already worth it.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;At the end of November though, Opus 4.5 had been released, and some time in December I decided to give it a try. It didn't seem massively different at first, but I was still working with it like it was Sonnet –&amp;nbsp;giving it small tasks, writing scripts, etc. It absolutely burned usage though, and until Opus I had never run into a limit before my usage counter reset. I literally didn't even realise there &lt;/span&gt;&lt;i&gt;&lt;em class="italic" style="white-space: pre-wrap;"&gt;was&lt;/em&gt;&lt;/i&gt;&lt;span style="white-space: pre-wrap;"&gt; a limit.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;It wasn't until I started asking it to implement features that I found it was making far fewer mistakes, and was in fact producing relatively good first passes.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;In October I had begun adding Github Copilot to some pull requests, and it had found a few issues. This was great, even if it came with some mistakes and noise. When you're a team of one and a half developers, an extra set of eyes is absolutely worth the trouble.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;Eventually the &lt;/span&gt;&lt;code spellcheck="false" style="white-space: pre-wrap;"&gt;&lt;span class="bg-gray-50 dark:bg-gray-800/30 font-mono px-2 py-0.5 rounded border border-gray-200/60 dark:border-gray-700/50 text-gray-800 dark:text-gray-200 relative before:absolute before:inset-0 before:bg-gradient-to-r before:from-blue-50/30 before:to-purple-50/30 dark:before:from-blue-900/20 dark:before:to-purple-900/20 before:-z-10"&gt;Co-authored-by: Copilot&lt;/span&gt;&lt;/code&gt;&lt;span style="white-space: pre-wrap;"&gt; notes start showing up more frequently in the commit logs, and I found it useful enough to pay for the basic subscription once my free tier limits ran out.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;By the end of December, I was hitting my Claude Code limits constantly. I started using "extra usage" which lets you spend a little more to get to the end of whatever was being worked on when the included limits were reached.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;I experimented with using GPT-5 and Opus via the Copilot extension included with VSCode. Once I run through the limits there, I start going through extra usage on that.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;figure class="image-wrapper"&gt;&lt;img src="/files/210bc16b22348def.png" alt="Metered usage.png" width="inherit" height="inherit" style="max-width: 100%; height: auto;"&gt;&lt;figcaption class="not-prose font-sans text-sm text-neutral-400 whitespace-pre-wrap break-words mt-2"&gt;The point at which Copilot started being very useful.&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;Using Copilot, I built the first application that I have not read line-by-line, &lt;/span&gt;&lt;a href="https://duggan.ie/vat-invoice-generator" rel="noreferrer"&gt;&lt;span style="white-space: pre-wrap;"&gt;a VAT invoice generator&lt;/span&gt;&lt;/a&gt;&lt;span style="white-space: pre-wrap;"&gt;. I needed to generate mock invoices to do some basic interactive testing of the OCR flow for Manano. As long as it generated something that looked plausible, it was fine, but I found that with GPT-5 doing the bulk of the actual coding, I was able to freewheel on ideas about design and local-first software.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;I wanted it to be like &lt;/span&gt;&lt;a href="https://tiddlywiki.com" rel="noreferrer"&gt;&lt;span style="white-space: pre-wrap;"&gt;Tiddlywiki&lt;/span&gt;&lt;/a&gt;&lt;span style="white-space: pre-wrap;"&gt;, where it could be used as a file on the desktop as easily as something at a URL. I wanted it to be WYSIWYG rather than a set of dull forms to fill out. And having a bunch of visually distinctive templates to make sure a variety of visual styles would work.&lt;/span&gt;&lt;/p&gt;&lt;h2 id="christmas-break-structured-prompts" class="group relative"&gt;&lt;a href="#christmas-break-structured-prompts" class="absolute -left-6 top-1/2 -translate-y-1/2 opacity-0 group-hover:opacity-100 transition-opacity duration-200 text-gray-400 hover:text-gray-600 no-underline"&gt;#&lt;/a&gt;&lt;span style="white-space: pre-wrap;"&gt;Christmas break, structured prompts&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;Over the Christmas period, while Ash was visiting her family, I had the opportunity to get stuck into the feature idea backlog for my blog. This felt like a good testing ground for the coding assistants, as it was a bit cobbled together, had gone through a few architectural lurches, but I had written enough of the codebase myself to evaluate the results.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;Also, being a blog, the stakes were low. Every time I'd have some idea for the blog I'd jot it down in Apple Notes. Here was what I had built up:&lt;/span&gt;&lt;/p&gt;&lt;aside class="callout my-6"&gt;&lt;div class="border-l-4 border-blue-500 bg-blue-50 dark:bg-blue-900/20 px-6 py-4 rounded-r-lg"&gt;&lt;strong class="block text-sm font-semibold uppercase tracking-wide text-blue-700 dark:text-blue-300"&gt;duggan.ie features/bugs&lt;/strong&gt;&lt;div class="mt-2 text-base leading-relaxed"&gt;&lt;p&gt;&lt;b&gt;&lt;strong style="white-space: pre-wrap;"&gt;Saving/updating published posts&lt;/strong&gt;&lt;/b&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;When a post has been published, any subsequent updates should include an optional reason for the update.&lt;/span&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;If a post is published, hitting save or using the save shortcut (Cmd+S) should pop up a dialog with a textbox to describe the reason for the change. This should be plaintext only, no special formatting.&lt;/span&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;It should still be possible to change without including a reason. In that case, the update should not change the updated_at marker.&lt;/span&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;The “save” target should move to the dialog box, so that hitting Cmd+S again will save the post.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;strong style="white-space: pre-wrap;"&gt;Changelog&lt;/strong&gt;&lt;/b&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;Include the post updates in published posts.&lt;/span&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;It should be implemented as a collapsed summary + details element at the bottom of the post.&lt;/span&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;It should also be included in the Atom feed.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;strong style="white-space: pre-wrap;"&gt;Feedback system for shared drafts&lt;/strong&gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;Goal: Create a feedback system for shared links.&lt;/span&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;Context:&lt;/span&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;Shared links are designed to be shared with a single person. The URLs are deliberately obfuscated and they have configurable expiry, after which they return 404.&lt;/span&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;The editor is built using Lexical, and stores the lexical node data in the post_revisions table, with a posts table to hold the rendered html and reference to the currently fresh post_revisions record.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;Implementation details:&lt;/span&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;Implement the feedback system as a Lexical plugin.&lt;/span&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;The shared links can use a Lexical editor with our feedback system plugin.&lt;/span&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;Other than using the feedback system, the shared link editor should be read-only – the user should just be making notes, not editing the text directly.&lt;/span&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;Each shared link will likely need to make a copy of the main editor node data on creation.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;Open questions:&lt;/span&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;How best to handle when the main editor updates the post data. Should the shared links be updated? Should the user get a note/bar at the top of the screen saying something like “the author has updated the draft, would you like to refresh?” etc.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;strong style="white-space: pre-wrap;"&gt;Opengraph integration for links&lt;/strong&gt;&lt;/b&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;When pasting a link into the editor, it should give me the option to include it as nicely formatted block with OpenGraph data (image, title, content, etc) like Notion.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;strong style="white-space: pre-wrap;"&gt;Video/image loading skeleton&lt;/strong&gt;&lt;/b&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;Context: images and videos can be dragged and dropped into the editor, and are displayed inline.&lt;/span&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;Goal: While the images are uploading, there should be a loading skeleton in place to show that it is being processed.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;strong style="white-space: pre-wrap;"&gt;Enhanced video/image resizing controls&lt;/strong&gt;&lt;/b&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;Context: image and video resizing in the editor is very basic&lt;/span&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;Goal: enhance the resize functionality so that arbitrary resizing is supported.&lt;/span&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;Additional support: helpful resize controls, like “original”, “full width”, etc., should be included&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;strong style="white-space: pre-wrap;"&gt;Light / Dark mode&lt;/strong&gt;&lt;/b&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;Initial change to light mode seems to result in a white screen&lt;/span&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;Continue button flashes when changing, sometimes on loadMake tags distinctive&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;b&gt;&lt;strong style="white-space: pre-wrap;"&gt;Tag management area&lt;/strong&gt;&lt;/b&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;Include emoji / stickers / SVG images as part of the tags&lt;/span&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;Should be able to specify a colour for each tag using a colour wheel, etc.&lt;/span&gt;&lt;br&gt;&lt;b&gt;&lt;strong style="white-space: pre-wrap;"&gt;V2&lt;/strong&gt;&lt;/b&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;More comprehensive emoji selector (with keyword search)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;strong style="white-space: pre-wrap;"&gt;Post list&lt;/strong&gt;&lt;/b&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;Add a new post status: archived&lt;/span&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;The post list navigation should be broken out by published vs draft vs archived in the left navigation.&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/aside&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;It was quite a decent chunk of work in my book.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;These notes were originally just for my own reference, but you'll notice that at some point I started editing the notes with a basic structure for Claude Code that I felt was clearer.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;I thought I'd make good headway on a few of them, but over the Christmas break I steamrolled &lt;/span&gt;&lt;i&gt;&lt;em class="italic" style="white-space: pre-wrap;"&gt;every one of them&lt;/em&gt;&lt;/i&gt;&lt;span style="white-space: pre-wrap;"&gt;, iterated on a few, and even added some extras once I ran out.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;I started out just about coming up short on Claude limits, having to wait 30 minutes or so before starting again. But by the end of this process I was smashing through those limits really quickly, and had to start getting more targeted and careful about what I wanted to work on.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;Eventually though, I was paying extra usage on both Copilot and Claude Code, still cheaper than springing for a higher usage plan, but chafing at the limits.&lt;/span&gt;&lt;/p&gt;&lt;h2 id="the-yegge-inflection-point" class="group relative"&gt;&lt;a href="#the-yegge-inflection-point" class="absolute -left-6 top-1/2 -translate-y-1/2 opacity-0 group-hover:opacity-100 transition-opacity duration-200 text-gray-400 hover:text-gray-600 no-underline"&gt;#&lt;/a&gt;&lt;span style="white-space: pre-wrap;"&gt;The Yegge Inflection Point&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;This month, I finally sprung for Claude Code Max –&amp;nbsp;though only 5x, not yet the 20x. It's just too powerful an upgrade on my capabilities as a developer to pass up. Other people can wait to see where it goes and look back on this period with sagacity and the wisdom of hindsight.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;I am still using Claude Code interactively in VSCode, I haven't gotten to the stage where I &lt;/span&gt;&lt;a href="https://steve-yegge.medium.com/welcome-to-gas-town-4f25ee16dd04" rel="noreferrer"&gt;&lt;span style="white-space: pre-wrap;"&gt;never read the code that's being produced&lt;/span&gt;&lt;/a&gt;&lt;span style="white-space: pre-wrap;"&gt;, though maybe I'll get there, too. Steve Yegge is there with a few other people, and they are probably living in &lt;/span&gt;&lt;i&gt;&lt;em class="italic" style="white-space: pre-wrap;"&gt;a&lt;/em&gt;&lt;/i&gt;&lt;span style="white-space: pre-wrap;"&gt; version of the future, but it's not the &lt;/span&gt;&lt;i&gt;&lt;em class="italic" style="white-space: pre-wrap;"&gt;only&lt;/em&gt;&lt;/i&gt;&lt;span style="white-space: pre-wrap;"&gt; version of the future.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;There are lots of different kinds of software. Not all of it will be amenable to this style of development.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;For a 20 year old aspiring software developer in college, I have no idea how they are going to get to their version of &lt;/span&gt;&lt;span class="tooltip-wrapper tooltip-trigger cursor-help underline decoration-dotted" data-tooltip="true"&gt;&lt;span style="white-space: pre-wrap;"&gt;mastery&lt;/span&gt;&lt;template data-tooltip-content=""&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;For want of a slightly less pretentious term. Basically I just mean skilled and experienced enough to be useful at their craft. Being able to dive deep, take responsibility, adapt and learn on the fly.&lt;/span&gt;&lt;/p&gt;&lt;/template&gt;&lt;/span&gt;&lt;span style="white-space: pre-wrap;"&gt;. I suspect it will be very different to mine, and will take a very different route. I think it will be daunting, but I hope exciting. Nobody starts off knowing how everything works.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;For me, it's exciting. If at the end of the day all I end up with is a bunch of completed side projects, it will have been money well spent.&lt;/span&gt;&lt;/p&gt;&lt;section class="changelog"&gt;&lt;hr&gt;&lt;p&gt;&lt;strong&gt;Changelog:&lt;/strong&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;time datetime="2026-02-08T23:21:38.000Z"&gt;Feb 8, 2026, 11:21 PM&lt;/time&gt; — Fixed formatting in notes.&lt;/li&gt;&lt;/ol&gt;&lt;/section&gt;</content>
    <link href="https://duggan.ie/posts/i-built-a-terminal-monitoring-app-and-custom-firmware-for-a-desktop-clock-with-claude" rel="alternate"/>
    <published>2026-02-07T21:42:11.094Z</published>
    <summary type="html">&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;The way that I've used AI for coding has changed drastically over the last year.&lt;/span&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre-wrap;"&gt;In fact, the rate at which it is changing is probably the most drastic element of it –&amp;nbsp;I can't recall any time since my first year of college, twenty years ago, that I've experienced such a rapid evolution in my own ability to &lt;/span&gt;&lt;i&gt;&lt;em class="italic" style="white-space: pre-wrap;"&gt;do stuff&lt;/em&gt;&lt;/i&gt;&lt;span style="white-space: pre-wrap;"&gt;.&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;This week I have written a fully self-contained system monitoring daemon and terminal UI, as well as custom Rust firmware for the Ulanzi TC001 desktop clock.&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="white-space: pre-wrap;"&gt;These are two projects that would have remained ideas, never making it out of my notes folder.&lt;/span&gt;&lt;/p&gt;</summary>
  </entry>
</feed>