<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>nemo.foo</title>
        <link>https://nemo.foo</link>
        <description>Thoughts and learnings as I take on new side projects. 15 yoe building software. Looking for the right side project to go full time with.</description>
        <language>en</language>
        <skibidi>toilet</skibidi>
        <lastBuildDate>Thu, 12 Mar 2026 08:04:48 GMT</lastBuildDate>
        
    <item>
        <title>ShipClip</title>
        <author>nemo</author>
        <link>https://nemo.foo/projects/shipclip</link>
        <pubDate>Wed, 25 Feb 2026 00:00:00 GMT</pubDate>
        <description><![CDATA[<p>A native macOS screen recording app for developers and creators — multi-track recording, timeline editing, camera PiP, zoom-to-click effects, and one-click sharing.</p>
]]></description>
        <content:encoded><![CDATA[<h2>ShipClip</br>
</h2><p>A native macOS screen recording app that handles recording, editing, and sharing in one place. Record your screen, camera, and audio as independent tracks, polish with professional effects, and share with a link — no Electron, no cloud dependency, no bloat.</p>
<p><strong>🌐 <a href="https://shipclip.app">shipclip.app</a></strong></p>
<h3>The Problems</br>
</h3><ol>
<li><strong>Bloated tools</strong>: Most screen recording apps are Electron wrappers or cloud-first SaaS products that feel sluggish and phone home constantly.</p>
</li>
<li><strong>Post-production pain</strong>: Getting polished results (zoom-to-click, camera PiP, click indicators) usually means bouncing between multiple apps.</p>
</li>
<li><strong>Privacy concerns</strong>: Many recording tools upload your content by default or require accounts just to record.</p>
</li>
</ol>
<h3>The Solution</br>
</h3><p>ShipClip handles the full workflow natively on macOS — capture, edit, and export without leaving the app.</p>
<p><strong>Recording</strong> — Full screen or single window at 60 FPS. Screen, system audio, microphone, and camera are captured as completely independent stems for full control during editing.</p>
<p><strong>Timeline editing</strong> — Non-destructive split, delete, mute, and solo operations with waveform visualization. Per-track volume control and audio mute regions. Draggable playhead and automatic time ruler scaling.</p>
<p><strong>Visual effects</strong> — Zoom-to-click with configurable zoom level (1x–3x) and smooth cubic easing. Click indicators with color-coded pulses (left/right click), optional click sounds, and cursor pulse animation. Custom cursor rendering with type detection (arrow, I-beam, pointer, resize).</p>
<p><strong>Camera PiP</strong> — Draggable picture-in-picture overlay recorded at 1080p. Background effects including Gaussian blur, person segmentation via Vision framework, solid color replacement, and full background removal. Keyframe-based positioning over time. Configurable size, corner radius, and frame styling.</p>
<p><strong>Screen styling</strong> — Canvas padding, rounded corners, and backgrounds (solid color, linear gradient with angle control, or custom image).</p>
<p><strong>Export</strong> — MP4 (H.264 + AAC) at native resolution and 60 FPS by default, with configurable resolution and frame rate for smaller file sizes and better web performance.</p>
<p><strong>Sharing</strong> — One-click upload to <a href="https://shipclip.app">shipclip.app</a> with shareable links and a web player. Local export to <code>~/Movies/ShipClip/</code> always available.</p>
<h3>Technical Stack</br>
</h3><ul>
<li><strong>App</strong>: Swift, SwiftUI, ScreenCaptureKit, AVFoundation, Metal for GPU-accelerated compositing, Vision framework for person segmentation</p>
</li>
<li><strong>Backend</strong>: .NET 9 Web API with PostgreSQL, Stripe billing, S3/R2 storage</p>
</li>
<li><strong>Frontend</strong>: Next.js + shadcn/ui for the landing page, account management, and web player</p>
</li>
<li><strong>Infrastructure</strong>: Docker on Kubernetes (k3s), CI/CD via GitHub Actions</p>
</li>
<li><strong>Updates</strong>: Sparkle auto-update framework with EdDSA-signed, notarized DMGs</p>
</li>
</ul>
<h3>Architecture</br>
</h3><p>ShipClip uses a stem-based architecture where each input (screen, system audio, mic, camera) is recorded independently and composed at playback and export time. A custom <code>AVVideoCompositing</code> implementation handles real-time effects rendering — the same Metal compositor powers both the timeline preview and the final export, so what you see is exactly what you get.</p>
<p>Sessions are stored as discrete stems (<code>screen.mov</code>, <code>system_audio.m4a</code>, <code>mic.m4a</code>, <code>camera.mov</code>) with a <code>session.json</code> manifest and auto-saved <code>edits.json</code> for non-destructive editing state.</p>
]]></content:encoded>
        <category>macOS</category>
      <category>Swift</category>
      <category>Screen Recording</category>
      <category>Video Editing</category>
      <category>Metal</category>
    </item>
    

    <item>
        <title>The OSRS Botting Problem Is Architectural</title>
        <author>nemo</author>
        <link>https://nemo.foo/blog/osrs-botting-problem-is-architectural</link>
        <pubDate>Sun, 18 Jan 2026 00:00:00 GMT</pubDate>
        <description><![CDATA[<p>I built a voice-controlled OSRS client to understand why botting persists. What I found: the problem isn't detection, it's architecture.</p>
]]></description>
        <content:encoded><![CDATA[<p>I wanted to understand why Old School RuneScape has such a persistent bot problem. So I built a voice-controlled client.</p>
<p>Not to cheat. To learn. Voice control seemed like a way to explore what the plugin API actually exposes without crossing ethical lines. I'd build something that required a human in the loop, and in the process, I'd see exactly what an automation developer sees.</p>
<p>What I found: botting isn't a detection problem. It's a client control problem. And it won't be solved until Jagex ships an official plugin API.</p>
<p><strong>Video version:</strong> [VIDEO_LINK_HERE]</p>
<p><strong>TL;DR:</strong> <em>RuneLite isn't bad, Jagex isn't lazy, and &quot;detect better&quot; isn't the answer. This is the cost of the community picking RuneLite over the official client.</em></p>
<p><strong>Live stats:</strong> <a href="/osrs-stats">Tracking RuneLite adoption after the Java client shutdown</a></p>
<hr>
<h2>What I Built</br>
</h2><p>I created a new ironman account, <code>voicescaper</code>, and set out to play the game by voice.</p>
<p>The tool has two pieces. A RuneLite plugin reads game state: where NPCs are, what's in my inventory, which tiles are walkable. An external application listens for speech, transcribes it locally, and translates commands into mouse clicks. Everything runs on my machine. No cloud services, no data leaving my computer.</p>
<p>Playing as <code>voicescaper</code> was humbling. I chopped trees, mined ore, talked to NPCs, attacked cows. The kinds of things you do in the first hour of any account. It worked, mostly. But voice recognition is unforgiving. &quot;Attack cow&quot; sometimes became &quot;a tank cow.&quot; Pathfinding meant saying &quot;move five tiles north&quot; and hoping I'd counted right.</p>
<p>After an hour, I was exhausted from talking and went back to clicking.</p>
<hr>
<h2>The Moment It Clicked</br>
</h2><p>But then I started thinking about what I'd actually built.</p>
<p>The plugin has access to complete game state. The external application can click anywhere on screen. The only thing making this a voice control tool instead of a bot is that a human provides the intent.</p>
<p>I didn't build autonomous automation. But the architecture would trivially support it. Swap out voice recognition for a decision loop, and you have a bot. The structural pieces are identical.</p>
<p>This is the core insight: the plugin API that enables quest helpers and ground markers also exposes everything automation needs. The hard part of botting, understanding what's happening in the game, is already solved by the same infrastructure that makes RuneLite useful.</p>
<hr>
<h2>Why This Matters</br>
</h2><p>When people talk about botting, the instinct is &quot;detect better&quot; or &quot;ban harder.&quot; But detection has structural limits.</p>
<p>Jagex can only see what reaches their servers: clicks arriving at plausible speeds. They can't see what's running on your machine, what plugins are loaded, or whether a human decided to click or a script did. From their side, a bot with full game state access looks identical to a player.</p>
<p>That's the problem. It's not that Jagex isn't trying. It's that the information they'd need to distinguish automation from legitimate play doesn't exist at the server level.</p>
<hr>
<h2>The Automation Landscape</br>
</h2><p>There are several ways people automate OSRS. Understanding them helps clarify where Jagex has leverage and where they don't.</p>
<p><strong>Network bots</strong> talk directly to Jagex's servers. No client, just raw packets. In theory, Jagex could change the protocol anytime. In practice, breaking RuneLite (which reverse-engineers the same protocol) creates friction.</p>
<p><strong>Memory bots</strong> attach to the running client and read game state from RAM. The standard defense is kernel-level anti-cheat like Vanguard or EasyAntiCheat. But that's invasive software, and you can't mandate it for a third-party client you don't control.</p>
<p><strong>Auto-clickers</strong> are simple input macros. These are actually detectable. Clicking the same pixel every 1.8 seconds for five hours is statistically obvious. But the moment automation has access to game state, it can vary timing and position to look human.</p>
<p><strong>Client plugins</strong> are where I operated, and where Jagex has the least leverage. The RuneLite API exposes complete game state. Anyone can fork the client, write unreviewed plugins, or bridge data to external programs. Jagex can't see what plugins you're running. They can't verify your client is legitimate.</p>
<p>Everything I built used public APIs. I didn't reverse-engineer anything. I used the same tools as tile markers and quest helpers.</p>
<hr>
<h2>What OSRS Can Learn from WoW</br>
</h2><p>World of Warcraft has supported add-ons for over twenty years. Thousands of developers. Deeply customizable UI. A massive plugin ecosystem.</p>
<p>And yet, WoW's add-on system doesn't meaningfully lower the barrier to automation. Not because Blizzard detects better, but because the API is intentionally constrained.</p>
<p>Like RuneLite, WoW add-ons can't generate input. No fake clicks or keypresses. The difference is everything around that constraint.</p>
<p>WoW add-ons run in a sandbox. They can display information and help you make decisions, but they can't hand that information to external programs. There's no bridge. If you want to build a WoW bot, you have to leave the add-on system entirely: memory reading, injection, OS-level input spoofing. Techniques that are harder to build and easier to detect.</p>
<p>RuneLite is different. Plugins run in a full JVM with access to complete game state. A plugin can trivially act as an oracle, packaging up coordinates, NPC positions, and interface state for whatever external tool wants to consume it. The plugin doesn't click. But it makes clicking programmatically easy.</p>
<p>Imagine if RuneLite's entity highlighter could show you where the fishing spot is, but couldn't tell an external program its exact screen coordinates. That's roughly what WoW enforces.</p>
<p>WoW has quest helpers too. Questie, RestedXP. But notice how they work: targeting icons, minimap markers, on-screen directions. Not direct entity outlines with pixel-perfect coordinates exposed to the API. Different levels of access. And critically, the data can't be bridged out.</p>
<p>Jagex needs an official client with a plugin API designed like WoW's. One that lets you build helpful tools without also enabling automation.</p>
<hr>
<h2>The Accessibility Angle</br>
</h2><p>Somewhere along the way I realized what I'd built had legitimate uses beyond my experiment. OSRS requires thousands of clicks per hour. That's fine if you have full use of your hands. It's a barrier if you don't.</p>
<p>Voice control isn't a competitive advantage. It's slower and less precise than a mouse. The human is still playing, still making decisions. The interface just changes how input is provided, not who provides it.</p>
<p>The uncomfortable part is that the same infrastructure supports both. An accessibility tool and a bot differ only in what drives decisions. Distinguishing between them technically is extremely difficult.</p>
<hr>
<h2>Why Jagex Is Stuck</br>
</h2><p>Jagex isn't lazy. They tried.</p>
<p>In May 2018, Jagex told RuneLite to shut down. Not &quot;remove these features.&quot; Shut down entirely. When Adam, the developer, asked what specifically violated their terms so he could fix it, Jagex wouldn't say. The demand was: close by the end of the week.</p>
<p>The community erupted. RuneLite had already become essential. Jagex backed down.</p>
<p>That moment forced a choice: client control or player retention. They chose openness. Botting became harder to fight as a direct result.</p>
<p>In June 2022, Jagex formalized the compromise with an approved client list. Only RuneLite and HDOS are permitted. Everything else gets you banned.</p>
<p>But an approved list doesn't give Jagex technical leverage. They still can't see what plugins are running. They still can't verify inputs came from legitimate play. They just narrowed the field of clients they're not actively fighting.</p>
<p><strong>Update (January 28, 2026):</strong> The legacy Java client had been deprecated for years. Jagex's reasoning for finally retiring it: &quot;the vast majority of users are botting.&quot; When the switch flipped, tens of thousands of accounts vanished from the player count overnight. This proves Jagex can still act decisively—but notice what they could act on: a client they control. RuneLite and HDOS remain untouched. I'm <a href="/osrs-stats">tracking RuneLite adoption</a> to see if those bots migrate.</p>
<hr>
<h2>The Roadmap</br>
</h2><p>RS3 is getting an official plugin API in 2026. Jagex announced a dedicated team building it.</p>
<p>Old School started down the same path. In July 2024, they announced a plugin API in development, built in collaboration with established plugin developers.</p>
<p>Then they paused it to prioritize HD rendering and mobile improvements.</p>
<p>I get it. HD and mobile are visible features. A plugin API is infrastructure. Hard to put in a trailer.</p>
<p>And to be fair, finishing the new renderer lets them retire legacy code. That cleanup positions them to build the API properly.</p>
<p>But infrastructure is how you solve this long-term. The anti-bot leverage that comes from client control doesn't exist until the API ships.</p>
<p>RS3 is getting this in 2026. Old School should too.</p>
<hr>
<h2>The Uncomfortable Reality</br>
</h2><p>There are three paths forward.</p>
<p><strong>Ban third-party clients.</strong> Close the vulnerability, lose a huge chunk of players. RuneLite isn't optional for most of the community anymore.</p>
<p><strong>Keep the status quo.</strong> Third-party clients stay legal. Botting stays viable. The cat-and-mouse continues indefinitely.</p>
<p><strong>Reclaim the client with a constrained plugin API.</strong> This is the only sustainable option. But it requires Jagex to control the runtime and define the extension boundaries. Copying RuneLite's features isn't enough. The API itself needs different constraints.</p>
<p>With client control, Jagex can ask &quot;did this come from software we trust?&quot; instead of &quot;does this look human?&quot; That's a different question. Bots are much worse at answering it.</p>
<p>There's a world where plugins exist and botting becomes meaningfully harder. It just can't be built on third-party clients.</p>
<hr>
<h2>Why I'm Writing This</br>
</h2><p>Some people will read this and think I'm enabling botters. I'm not.</p>
<p>The dynamics I'm describing are already well understood by people who build bots. I'm explaining them to everyone else: players frustrated by gold farmers, community members who think Jagex isn't trying hard enough.</p>
<p>You get a remarkable plugin ecosystem and major quality-of-life improvements. You also get an automation surface that can't be fully closed. These aren't separate issues. They're the same architectural choice, viewed from different angles.</p>
<hr>
<h2>A Note on Implementation</br>
</h2><p>I'm deliberately not providing technical specs or library names beyond what's necessary to make the argument.</p>
<p>The goal is to explain why the botting problem is structural, not to hand out a reference implementation. Anyone determined to build automation doesn't need my help.</p>
<p>The tool runs entirely locally. No cloud services, no data collection.</p>
<hr>
<h2>What I'd Like to See</br>
</h2><p><strong>Unpause the plugin API.</strong> HD is great. Mobile matters. But the API is how you get long-term leverage. It should be a priority.</p>
<p><strong>Design it with WoW's lessons in mind.</strong> Intentional limits. A sandbox that exposes information without exposing control. Protected functions that can't be called programmatically.</p>
<p><strong>Work with RuneLite.</strong> The RuneLite team built something remarkable. They understand what plugins need. Collaborate on what a healthy API looks like.</p>
<p>If anyone at Jagex wants to talk about client architecture or plugin tradeoffs, I'm available. I'm not interested in enabling gold farmers. I love this game and want it to be around for a long time.</p>
<p>Also, if you're hiring for the bot-busting team, I'd love to help.</p>
<hr>
<h2>References</br>
</h2><ul>
<li><a href="https://runelite.net/blog/show/2018-05-15-RuneLite-threatened-to-shutdown/">RuneLite threatened to shutdown (May 2018)</a></p>
</li>
<li><a href="https://www.reddit.com/r/oldschoolrs/comments/8jq444/runelite_threatened_to_shutdown/">Reddit thread on shutdown threat</a></p>
</li>
<li><a href="https://youtu.be/lJXp5ahFOBk">&quot;Why Jagex Tried To Sue RuneLite. The True Story&quot; by ColonelloRS</a></p>
</li>
<li><a href="https://youtu.be/B8i26g45WeY">&quot;How Cheaters Defeated RuneScape's Best Bot Detection&quot; by ColonelloRS</a></p>
</li>
<li><a href="https://www.youtube.com/watch?v=Nxkc9tpsL3Y">&quot;I Interviewed Adam the Founder of RuneLite&quot; by Crumb</a></p>
</li>
<li><a href="https://www.youtube.com/watch?v=3JhKU_ujlhs">&quot;this trend in gaming makes me very concerned.&quot; by LowLevelTV</a></p>
</li>
<li><a href="https://www.youtube.com/watch?v=VtHlMTc8lR4">&quot;i was right (again).&quot; by LowLevelTV</a></p>
</li>
<li><a href="https://wowpedia.fandom.com/wiki/Secure_Execution_and_Tainting">WoW Secure Execution and Tainting (Wowpedia)</a></p>
</li>
<li><a href="https://www.wowinterface.com/forums/showthread.php?t=27189">WoW AddOn Security Discussion (WoWInterface)</a></p>
</li>
<li><a href="https://secure.runescape.com/m=news/third-party-clients-update?oldschool=1">Jagex third-party clients update (June 2022)</a></p>
</li>
<li><a href="https://secure.runescape.com/m=news/new-official-client--next-steps?oldschool=1">New official client announcement (July 2023)</a></p>
</li>
<li><a href="https://secure.runescape.com/m=news/official-client-update---july-2024?oldschool=1">Official client update, plugin API announced (July 2024)</a></p>
</li>
<li><a href="https://secure.runescape.com/m=news/the-roadmap-that-changes-runescape-forever">RS3 2026 roadmap, plugin API confirmed</a></p>
</li>
<li><a href="https://secure.runescape.com/m=news/a=97/winter-summit-2026---overview?oldschool=1#HD">OSRS Winter Summit 2026, HD prioritized, plugin API paused</a></p>
</li>
<li><a href="https://secure.runescape.com/m=news/holy-moleys-and-the-hooded-slayer-helm-are-here?oldschool=1">Java Client discontinued, &quot;vast majority of users are botting&quot; (January 2026)</a></p>
</li>
<li><a href="https://oldschool.runescape.wiki/w/Java_Client">Java Client history (OSRS Wiki)</a></p>
</li>
<li><a href="https://www.reddit.com/r/2007scape/comments/1qpdym0/bot_nuke_2026/">Reddit: &quot;Bot Nuke 2026&quot; - 55,000 players vanished overnight</a></p>
</li>
</ul>
<hr>
<p><em>I set out to understand why OSRS has a botting problem. I ended up learning it's architectural, not a detection problem. And it won't change until Jagex controls the client.</em></p>
]]></content:encoded>
        <category>blog</category>
      <category>osrs</category>
      <category>runelite</category>
      <category>case-study</category>
    </item>
    

    <item>
        <title>Walking Away from $200k</title>
        <author>nemo</author>
        <link>https://nemo.foo/blog/walking-away-from-200k</link>
        <pubDate>Sat, 21 Jun 2025 00:00:00 GMT</pubDate>
        <description><![CDATA[<p>I'm walking away from 200k in unvested stock to get my life back. Last week, I handed in my notice and walked away from my golden handcuffs.</p>
]]></description>
        <content:encoded><![CDATA[<p>I'm walking away from 200k in unvested stock to get my life back.</p>
<p>Last week, I handed in my notice and walked away from my golden handcuffs. I'm leaving $200k in unvested stock left on the table.</p>
<p>Is that wise? Depends on what you value.</p>
<p>I wasn't seeing my wife or toddler, I wasn't building anything for myself anymore, and I was watching my goals evaporate in a cloud of Slack pings and badge swipes.</p>
<p>So I made the call. I'm going back to a remote job, and setting a five year goal to earn $200k from side projects instead.</p>
<h2>What Happened</br>
</h2><p>I was hired as a hybrid 2 days a week in office role. Then the stock price shot up. Then came the RTO (return to office), the reorgs, the demands, the culture. You know the story.</p>
<p>At first, I thought I could power through. I'd just keep stacking cash, ride the vesting curve, buy time later. And I did hit the vesting cliff. I've got some equity in my pocket. But the rest? The real upside? That's more time, more sacrifice, more office.</p>
<p>Meanwhile...</p>
<p>Side projects? Dead.</p>
<p>Weeknights? Gone.</p>
<p>Weekends? Recovery mode.</p>
<p>Family time? Maybe two hours a day, and I wasn't even present for half of it.</p>
<p>At some point, I realized I was working for a version of me that doesn't exist anymore.</p>
<h2>The Tradeoff</br>
</h2><p>$200k is a lot of money. It's painful to walk away from. But stock isn't just money. It's a bet. And in my case, it was a bet that required me to burn out slowly over the next few years.</p>
<p>
<br/>
<img src="/rsu-account-screenshot.webp" alt="" style="max-width:100%"/></p>
<p>Meanwhile, my kid is growing up now. My wife and I are trying to build a life with margin, not just money. I've spent 15 years learning how to build. It's time to apply it to something that's mine.</p>
<p>So here's the new goal:</p>
<p><strong>Make $200k from side projects by 2030.</strong></p>
<p>Not overnight. Not with a viral launch or SaaS rocketship.</p>
<p>Slow. Intentional. Profitable from the start. Built to last.</p>
<h2>Side Contracts</br>
</h2><p>In addition to building product, I'm also leaning on my freelance brand, Ligma Digital, to bring in revenue from consulting and dev work. I've already built a lead gen bot. So far, I've got a few warm leads and potential contracts in the $10k+ range.</p>
<p>And now that I'm going remote again, I get back about three hours a day on weekdays that used to vanish into commuting and office overhead. That's over 750 hours a year.</p>
<p>Even if I bill just a portion of that time, I should exceed the $200k target by a wide margin. And the rest of the hours? I get to spend them with my family or invest in building something real.</p>
<h2>First Project: Andon Lamp</br>
</h2><p>You know how you're constantly alt-tabbing to check if your AI tool is done thinking?</p>
<p>Andon Lamp fixes that. It's a desk device that glows based on your AI assistant's status. You can stay in flow, keep your hands on the keyboard, and stop babysitting the process.</p>
<p>
<br/>
<img src="/andon-200k.webp" alt="" style="max-width:100%"/></p>
<p>I built it with a Rust CLI, a Raspberry Pi Pico, and a string of RGBW LEDs.</p>
<p>It's vibey. It's functional. It's already saving me context switches.</p>
<p>🎥 <a href="https://youtu.be/6etSUhWwFwQ">Watch the demo</a> →</p>
<p><a href="https://getandon.com">Pre-order at getandon.com</a> →</p>
<h2>Who This Is For</br>
</h2><p>This mission isn't just about me. It's for:</p>
<ul>
<li>Developers who want out of the full time trap</p>
</li>
<li>Parents who don't want to miss the good stuff</p>
</li>
<li>Builders who've flopped a few projects but still have the itch</p>
</li>
</ul>
<p>If that's you: hey. Let's build in public together.</p>
<h2>Follow Along</br>
</h2><p>I'll be sharing everything here:</p>
<ul>
<li>Revenue numbers</p>
</li>
<li>Project breakdowns</p>
</li>
<li>Monthly updates</p>
</li>
<li>What works (and what definitely doesn't)</p>
</li>
</ul>
<p>📬 Join the email list below →</p>
<p>📺 <a href="https://youtube.com/@nemosaurus">Subscribe on YouTube</a> →</p>
<p>0 / 200k. One step at a time.</p>
]]></content:encoded>
        <category>blog</category>
      <category>goals</category>
      <category>career</category>
      <category>side-projects</category>
    </item>
    

    <item>
        <title>Andon Lamp</title>
        <author>nemo</author>
        <link>https://nemo.foo/projects/andon-lamp</link>
        <pubDate>Sat, 07 Jun 2025 00:00:00 GMT</pubDate>
        <description><![CDATA[<p>The evolution of DeskThang - a comprehensive LED status indicator system for AI agents and workflow monitoring.</p>
]]></description>
        <content:encoded><![CDATA[<h2>Andon Lamp</br>
</h2><p>The evolution of DeskThang - a comprehensive LED status indicator system built for Raspberry Pi Pico, designed to provide visual feedback for AI agent states and general status monitoring.</p>
<p><strong>🌐 Visit <a href="https://getandon.com">getandon.com</a> for the complete experience.</strong></p>
<h3>The Evolution</br>
</h3><p>Andon builds upon the foundation established by <a href="/projects/deskthang">DeskThang</a>, pivoting from a complex LCD-based system to a focused, reliable LED status indicator. While DeskThang explored many concepts, Andon represents a refined vision with clear purpose and production-ready implementation.</p>
<h3>Key Features</br>
</h3><ul>
<li><strong>RGBW LED Strip</strong>: 38 SK6812 LEDs with individual control</p>
</li>
<li><strong>Status Indicators</strong>: OK (green), Warning (yellow), Error (red), Info (blue)</p>
</li>
<li><strong>Desk Lamp Mode</strong>: White balance control for ambient lighting</p>
</li>
<li><strong>AI Integration</strong>: MCP server for direct Claude and AI system integration</p>
</li>
<li><strong>Patterns</strong>: Rainbow, chase, fade, pulse, and custom effects</p>
</li>
</ul>
<h3>Technical Stack</br>
</h3><ul>
<li><strong>Firmware</strong>: C code running on Raspberry Pi Pico with modular architecture</p>
</li>
<li><strong>Host Application</strong>: Rust CLI for cross-platform USB communication</p>
</li>
<li><strong>MCP Server</strong>: Node.js server for AI system integration</p>
</li>
<li><strong>Hardware</strong>: RP2040 microcontroller, SK6812 RGBW LED strip, USB connection</p>
</li>
</ul>
<h3>Design Philosophy</br>
</h3><ol>
<li><strong>Focused Purpose</strong>: Clear visual status indication without complexity</p>
</li>
<li><strong>Modular Architecture</strong>: Clean separation of concerns and maintainable code</p>
</li>
<li><strong>AI-First</strong>: Built specifically for AI agent workflow integration</p>
</li>
<li><strong>Production Ready</strong>: Reliable hardware and robust software</p>
</li>
</ol>
<h3>Command Interface</br>
</h3>
<br/>
<pre><code># Status control
andon-cli status ok          # Green pulsing
andon-cli status warning     # Yellow pulsing
andon-cli status error       # Red pulsing
andon-cli status clear       # Clear status

# Desk lamp mode
andon-cli lamp on            # Ambient lighting
andon-cli white 200          # White balance control
</code></pre>
<br/><h3>Current Status</br>
</h3><p>Andon is actively developed with stable firmware, cross-platform host application, and comprehensive AI integration through MCP.</p>
<p>Visit <a href="https://getandon.com">getandon.com</a> to get started, or check out the <a href="/projects/deskthang">DeskThang project</a> to see where it all began.</p>
]]></content:encoded>
        <category>Hardware</category>
      <category>Embedded</category>
      <category>Rust</category>
      <category>C</category>
      <category>LED</category>
      <category>AI Integration</category>
    </item>
    

    <item>
        <title>Ligma Digital</title>
        <author>nemo</author>
        <link>https://nemo.foo/projects/ligma-digital</link>
        <pubDate>Sat, 07 Jun 2025 00:00:00 GMT</pubDate>
        <description><![CDATA[<p>Freelance software development and technical consulting services specializing in modern web applications, embedded systems, and AI integrations.</p>
]]></description>
        <content:encoded><![CDATA[<h2>Ligma Digital</br>
</h2><p>Professional freelance software development and technical consulting services, delivering custom solutions for modern web applications, embedded systems, and AI integrations.</p>
<p><strong>🌐 Visit <a href="https://ligma.digital">ligma.digital</a> for services and portfolio.</strong></p>
<h3>Services Offered</br>
</h3><p><strong>Web Development</strong></p>
<ul>
<li>Full-stack applications using modern frameworks (Next.js, Vue.js, React)</p>
</li>
<li>Backend APIs and microservices (.NET, Node.js, Python)</p>
</li>
<li>Database design and optimization (PostgreSQL, MongoDB)</p>
</li>
<li>Cloud deployment and DevOps (AWS, Docker, CI/CD)</p>
</li>
</ul>
<p><strong>Embedded Systems</strong></p>
<ul>
<li>Firmware development for microcontrollers (RP2040, ESP32)</p>
</li>
<li>Hardware prototyping and PCB design</p>
</li>
<li>IoT solutions and sensor integration</p>
</li>
<li>Real-time systems and communication protocols</p>
</li>
</ul>
<p><strong>AI Integration</strong></p>
<ul>
<li>Custom AI tool development and automation</p>
</li>
<li>Model Context Protocol (MCP) server implementation</p>
</li>
<li>Workflow optimization and intelligent systems</p>
</li>
<li>AI-powered application features</p>
</li>
</ul>
<h3>Technical Expertise</br>
</h3><ul>
<li><strong>Languages</strong>: Rust, C, JavaScript/TypeScript, Python, C#, Zig</p>
</li>
<li><strong>Frameworks</strong>: Next.js, Vue.js/Nuxt, .NET, Express.js</p>
</li>
<li><strong>Databases</strong>: PostgreSQL, MongoDB, Redis, SQLite</p>
</li>
<li><strong>Cloud</strong>: AWS, Docker, Kubernetes, CI/CD pipelines</p>
</li>
<li><strong>Hardware</strong>: Raspberry Pi Pico, Arduino, PCB design, 3D printing</p>
</li>
</ul>
<h3>Project Approach</br>
</h3><ol>
<li><strong>Discovery</strong>: Understanding requirements and technical constraints</p>
</li>
<li><strong>Architecture</strong>: Designing scalable, maintainable solutions</p>
</li>
<li><strong>Development</strong>: Iterative development with regular client feedback</p>
</li>
<li><strong>Deployment</strong>: Production-ready deployment with documentation</p>
</li>
<li><strong>Support</strong>: Ongoing maintenance and feature development</p>
</li>
</ol>
<h3>Recent Work</br>
</h3><ul>
<li><strong>AI-Powered Applications</strong>: Custom MCP servers and intelligent automation tools</p>
</li>
<li><strong>Embedded LED Systems</strong>: Hardware and firmware for status indication devices</p>
</li>
<li><strong>Web Platforms</strong>: Community-driven applications with modern tech stacks</p>
</li>
<li><strong>Hardware Prototypes</strong>: Custom PCB design and embedded system development</p>
</li>
</ul>
<h3>Current Availability</br>
</h3><p>Accepting new projects with focus on:</p>
<ul>
<li>AI integration and automation solutions</p>
</li>
<li>Embedded systems and hardware projects</p>
</li>
<li>Modern web application development</p>
</li>
<li>Technical consulting and architecture review</p>
</li>
</ul>
<p>Contact <a href="https://ligma.digital">ligma.digital</a> to discuss your project requirements and get a custom proposal.</p>
]]></content:encoded>
        <category>Freelance</category>
      <category>Consulting</category>
      <category>Web Development</category>
      <category>Embedded Systems</category>
      <category>AI Integration</category>
    </item>
    

    <item>
        <title>Build Your Own Tools - No One Else Will</title>
        <author>nemo</author>
        <link>https://nemo.foo/blog/build-your-own-tools</link>
        <pubDate>Sun, 06 Apr 2025 00:00:00 GMT</pubDate>
        <description><![CDATA[<p>When work ties your hands, building your own tools, both in the office and the garage, can be the key to moving faster, reclaiming agency, and actually enjoying the process again.</p>
]]></description>
        <content:encoded><![CDATA[<p><strong>TL;DR:</strong> Tired of waiting for permission to fix broken stuff? Build your own tools.</p>
<h2>The Work Dilemma</br>
</h2><p>In enterprise software, the pressure is always the same: deliver more, deliver faster. But at the same time, the systems you rely on are off-limits. You're not allowed to poke around in the guts, even if those guts are on fire. Priorities are set by the product team, and internal tooling always comes last, if it's ever considered at all.</p>
<p>Tech debt? We'll talk about that later, but later never comes. The opportunity cost of fixing what's broken is always weighed against shipping new features. &quot;We can't spend two sprints refactoring when we could be building the new analytics dashboard!&quot; Never mind that the current dashboard is held together with duct tape and prayers. The pressure to never look back, to never clean up what you've built, turns your codebase into a game of Jenga that nobody wants to touch.</p>
<p>You're expected to run a race, but you're not allowed to lace your own shoes. Or check if they're on the right feet. Or if you're even wearing shoes.</p>
<h2>The Epiphany: Build Your Own Tools</br>
</h2><p>The epiphany didn't come from writing code, it came from woodworking.</p>
<p>In the shop, it's completely normal to spend hours building templates or jigs before making a single real cut. A botched cut on a $300 slab can blow the whole project (and your weekend). So you invest in the things that reduce risk and make future work easier, even if that means stopping to build the tools first.</p>
<p>That same mindset clicked for me at work. If I'm tripping over the same problem more than once, that's a sign: build the tool. Make the jig. Automate the annoying part. Future You will say thanks. Present You will at least grumble less.</p>
<p>It's not rebellion, it's just how you get things done when the system around you won't help.</p>
<h2>DeskThang: A Case Study</br>
</h2><blockquote>
<p>I've been working on a little project called DeskThang, a physical device that lives on your desk and quietly tells you what you care about.</p>
</blockquote>
<br/><p>
<br/>
<img src="/blog-content/build-your-own-tools/deskthang-green-me-min.png" alt="" style="max-width:100%"/></p>
<ul>
<li>CI pipeline failed? Red flashing</p>
</li>
<li>Stripe sale? Purple pulse</p>
</li>
<li>Cursor's agent mode is waiting for you? Blue glow</p>
</li>
<li>Want something else? Fully scriptable from bash:</p>

<br/>
<pre><code>deskthang led 00ff00    # Set LED to green
deskthang image test.png # Display an image
</code></pre>
<br/></li>
</ul>
<p>It's scriptable, open-source, works over USB, and doesn't spy on you. Designed for people like me, devs who want ambient context without Slack pings, browser tabs, or pulling out a phone to get sucked into the void. (<a href="http://deskthang.com">deskthang.com</a>)</p>
<p>I started with a 3D-printed enclosure, which works well to show off the concept. But I want more. I want something beautiful, a device I'll be proud to leave on my desk. Something with wood, weight, and actual presence.</p>
<p>So I set out to build a wooden version.</p>
<p>That meant learning how to kerf-bend 1/8&quot; Baltic birch plywood. Mine is made up of three layers. The trick is to cut just deep enough, through about 1.75 layers, so the outer veneer stays intact and bends without snapping. We're talking about a margin of error of 0.2mm-cut 1.8mm when you need 1.6mm and it snaps. Go too shallow at 1.4mm and it won't bend at all. Every cut has to be that precise, dozens of times across the piece.</p>
<p>
<br/>
<img src="/blog-content/build-your-own-tools/kerf-bend.png" alt="" style="max-width:100%"/></p>
<p>Then comes the steaming. You've got to soften the wood before shaping it into curves. Only after it cools and dries do you get to see if your spacing and depth were consistent enough to hold a clean bend.</p>
<p>It's taken a lot of trial and error, but each iteration got better as I improved my process. Without the sleds, the jigs, the templates, and without CAD and Blender for modeling and fit checks, it wouldn't be possible. It's the same mindset as building software tools: remove the friction, one annoying detail at a time.</p>
<p>
<br/>
<img src="https://youtu.be/EQXRSVmZTXY" alt="" style="max-width:100%"/></p>
<p>
<br/>
<img src="https://youtu.be/vBoUjOXry78" alt="" style="max-width:100%"/></p>
<p>Same lesson: when the process sucks, pause and build the thing that makes it suck less.</p>
<p>Bonus: now I get to pretend I'm an old-world craftsman and ship functional hardware.</p>
<p>Next post: we'll get into epoxy resin art and building custom light pipes for the wooden version. I've got some glow experiments queued up.</p>
<h2>Why This Matters</br>
</h2><p>At work, no one's going to hand you the time or space to fix broken workflows. But you can sneak efficiency in through the side door. A script here. A CLI tool there. A bit of automation no one asked for, but everyone mysteriously starts using.</p>
<p>At home, you can go even further. You can build for joy. You can experiment. You can turn a bad cut into a better jig.</p>
<p>Tools aren't just about speed, they're about predictability. Predictable means repeatable, repeatable means reliable, and reliable means fast.</p>
<p>Every tool you build removes guesswork, smooths friction, and transforms uncertainty into clarity. And clarity is always quicker.</p>
<h2>Closing Thought</br>
</h2><p>If something keeps slowing you down, stop. Step back. Ask yourself: could I build something that fixes this?</p>
<p>Whether you're coding, crafting, cooking, or managing a team, the principle stays the same: when friction slows you down, build the tool that speeds you up. The solution might be a script, a jig, a checklist, or a new process-but the mindset of building your own tools applies everywhere.</p>
<p>More often than not, the answer is yes, and no one else is going to do it for you.</p>
]]></content:encoded>
        <category>blog</category>
      <category>tools</category>
      <category>deskthang</category>
      <category>woodworking</category>
    </item>
    

    <item>
        <title>TTRPG List</title>
        <author>nemo</author>
        <link>https://nemo.foo/projects/ttrpglist</link>
        <pubDate>Sat, 29 Mar 2025 00:00:00 GMT</pubDate>
        <description><![CDATA[<p>A community-driven platform to discover and promote lesser-known tabletop role-playing games, built by a solo developer with a passion for storytelling.</p>
]]></description>
        <content:encoded><![CDATA[<h2>TTRPG List</br>
</h2><p>TTRPG List is a web platform dedicated to helping tabletop role-playing game (TTRPG) creators share their work and players discover new adventures, free from the shadow of mainstream titles.</p>
<h3>The Problems</br>
</h3><ol>
<li><strong>Overshadowed Creativity</strong>: Countless innovative TTRPGs struggle to find an audience because they're buried under popular, big-budget games.</p>
</li>
<li><strong>Disconnected Communities</strong>: During times of isolation, like the COVID-19 pandemic, finding meaningful ways to connect through games was a challenge.</p>
</li>
<li><strong>Corporate Influence</strong>: Large platforms often prioritize profit over passion, leaving indie creators without a voice.</p>
</li>
</ol>
<h3>The Solution</br>
</h3><p>TTRPG List is a simple, community-focused site that:</p>
<ul>
<li>Allows creators to submit and feature their games</p>
</li>
<li>Provides a searchable database of TTRPGs with tags and systems</p>
</li>
<li>Encourages discovery through a clean, user-friendly interface</p>
</li>
<li>Fosters a space for players and creators to connect over unique, imaginative games</p>
</li>
</ul>
<h3>Technical Stack</br>
</h3><ul>
<li><strong>Frontend</strong>: Vue.js with Nuxt for a fast, server-rendered, and responsive user interface</p>
</li>
<li><strong>Backend</strong>: .NET API for robust server-side logic and user management</p>
</li>
<li><strong>Database</strong>: PostgreSQL for reliable storage of game data, tags, and systems</p>
</li>
<li><strong>Storage</strong>: Amazon S3 for hosting game images and assets</p>
</li>
<li><strong>Email</strong>: SendGrid for sending registration, notification, and update emails</p>
</li>
</ul>
<h3>Design Philosophy</br>
</h3><ol>
<li><strong>Community First</strong>: A platform built for and by the TTRPG community, not corporate interests.</p>
</li>
<li><strong>Transparency</strong>: Open about the solo development process and how featured content supports the site.</p>
</li>
<li><strong>Simplicity</strong>: Easy navigation and submission process to encourage participation.</p>
</li>
<li><strong>Imagination Unleashed</strong>: A focus on games that push boundaries and explore new ideas.</p>
</li>
</ol>
<h3>Features</br>
</h3><p>TTRPG List offers:</p>
<ul>
<li><strong>Game Submission</strong>: Creators can add their games with details, tags, and links.</p>
</li>
<li><strong>Search and Filter</strong>: Players can browse by tags (e.g., &quot;fantasy,&quot; &quot;sci-fi&quot;) or systems (e.g., &quot;D20,&quot; &quot;PbtA&quot;).</p>
</li>
<li><strong>Featured Games</strong>: Optional promotion for creators to boost visibility.</p>
</li>
<li><strong>User Accounts</strong>: Basic login/register system for submitting and managing content.</p>
</li>
</ul>
<p>Example usage:</p>
<ul>
<li>A player searches for &quot;solo TTRPGs&quot; and finds a hidden gem.</p>
</li>
<li>A creator submits their game with tags like &quot;horror&quot; and &quot;narrative,&quot; reaching new fans.</p>
</li>
</ul>
<h3>Current Status</br>
</h3><p>This project is a solo labor of love, actively maintained with plans for growth:</p>
<ul>
<li>Enhancing search functionality with advanced filters</p>
</li>
<li>Exploring community forums for discussion and feedback</p>
</li>
<li>Adding tools to assist creators in game development</p>
</li>
<li>Keeping the site sustainable through optional featured content</p>
</li>
</ul>
<p>Follow my journey on <a href="https://bsky.app/profile/nemo.foo">Bluesky (bsky.app/profile/nemo.foo)</a> or reach out at <a href="mailto:nemo@ttrpglist.com">nemo@ttrpglist.com</a> to share ideas and feedback!</p>
<hr>
]]></content:encoded>
        <category>Web Development</category>
      <category>TTRPG</category>
      <category>Community</category>
    </item>
    

    <item>
        <title>My Afternoon Project Turned Into Four Days of AI Lies, USB Chaos, and Hard Lessons</title>
        <author>nemo</author>
        <link>https://nemo.foo/blog/day-4-of-an-afternoon-project</link>
        <pubDate>Sun, 26 Jan 2025 00:00:00 GMT</pubDate>
        <description><![CDATA[<p>A quick project spiraled into a marathon of AI missteps, hardware headaches, and hard-earned lessons. Welcome to the story of Deskthang.</p>
]]></description>
        <content:encoded><![CDATA[<p><strong>TLDR - AI isn't a co-pilot; it's a junior dev faking competence. Trust it at your own risk.</strong></p>
<p>I'm 4 days into an afternoon project. I was so sure I'd crush this one. I had a good plan and the stoke was high. Let me introduce <em>Deskthang</em>. It's a thang for your desk. When I work, I want to put my phone in the other room, and only get the important notifications (thangs) in a different way. If my deployment pipeline fails, I want a globe on my desk to turn red and show me a gitlab logo. I do not want to check my phone or email or anywhere a distraction might find me.</p>
<blockquote>
<p>Quick backstory: I work full time++ doing boring enterprise software dev and rarely get to flex my engineering skills. While my title says engineer, I'd disagree.</p>
</blockquote>
<br/><h2>The Problem I'm Trying to Solve</br>
</h2><p>I always try to align multiple interests for a side project. I wanted to pull my electronics hardware box out of storage, I wanted to solve the notifications and focus issue for myself, and I wanted to see how scared I should be about AI taking my job. As they say, I was trying to get a few birds stoned at once.</p>
<p>
<br/>
<img src="https://nemo.foo/blog-content/deskthang/two_birds_stoned.gif" alt="" style="max-width:100%"/></p>
<h3>1. I miss working with hardware.</br>
</h3><p>During COVID lock-downs I landed an R&amp;D contract for a IoT Prototype. That R&amp;D job was the most fulfilling work of my career. I worked with a small, scrappy team with some of my best friends. I was 3D printing models, soldering components, writing embedded C, and field-testing with mechanical engineers... Real engineers. We worked hard, often late into the night, and the collaboration felt more like playing StarCraft with the boiz than a 9-to-5. I've missed that deeply ever since. Recently, I've been inspired recently by <a href="https://x.com/_MaxBlade">@_MaxBlade and DeskHub</a> and wanted to brush the dust off my electronics skills.</p>
<h3>2. I hate the UX of MFA (Multi Factor Authentication).</br>
</h3><p>I use GitLab heavily for CI/CD with my personal Kubernetes projects. Knowing the status of my pipelines is crucial... broken builds could disrupt all 7 of my users! Logging into GitLab feels like getting stabbed in the spleen. Every time I log in (multiple times a day), I face captchas, authenticator apps, or waiting for email codes, followed by yet another captcha. I've tried pipeline notifications through Slack, Discord, and Telegram, but those apps are like productivity black holes. I don't want my phone near me while working, or to open chat apps that derail my focus. Removing these distractions keeps me locked in.</p>
<h3>3. I want to see how good these AI tools are.</br>
</h3><p>I want to figure out if AI is going to take my job. I'm skeptical it can replace what I do, but I like testing my assumptions. Sometimes AI surprises me; other times, it's just a rabbit hole of wasted hours when I avoid doing real thinking.</p>
<p>Recently, I used Claude Sonnet 3.5 to brute-force hundreds of React compile errors while upgrading a project from React 15 to 18. I threw <code>package.json</code> updates, deleted <code>node_modules</code>, and burned through a small fortune in AI tokens. To my surprise, we had a passing build by the end of the day. Work has been encouraging us to adopt an AI-first workflow and giving us unlimited tokens. It's a wild experiment.</p>
<p>This happened on a Friday. I wiped the sweat off my brow after a hard day's prompting, and headed home early to start on my side project...</p>
<h2>The Plan</br>
</h2><p>Unlike me, my wife likes to leave the house and do things. I've spent a few years turning my garage into my favorite place to be. My wife and I have a deal where 1 day a month, She takes the kiddo and I am absolved of all responsibilities. I get a full day to lock in and build projects. From her perspective, I order doordash and turn into a degen who is unfit to father. From my perspective, I get to enjoy my favorite place and just tinker or play games or do whatever. These are the days I get to play mad scientist and feel most like myself. I look forward to it every month. My plan was to learn zig, brush off my hardware skills, build this project, write a blog post and make a video about it. Totally achievable.</p>
<p>I wanted to wire up a Raspberry Pi Pico, a small 240x240 LCD display and some RGB LEDs. I was going to learn Zig and use it to send image data over USB to the pico which will put an image on the screen and change the LED color. I would set up webhooks from GitLab to call an API in my Kube cluster and setup my host Zig app to poll that same API for changes and send updates to the Pico. I really wanted to transmit the data over USB because I've never done that before. I've already used Bluetooth, LTE and Wifi and just wanted to do something new.</p>
<p>The wiring is simple. Common patterns I was familiar with like <a href="https://en.wikipedia.org/wiki/Serial_Peripheral_Interface">SPI (Serial Peripheral Interface)</a> for the display + some RGB leds. The <a href="https://itsfoss.com/what-is-tty-in-linux/?utm_source=chatgpt.com">TTY (TeleTYpewriter)</a> serial data port on Linux <code>/dev/ttyACM0</code> for USB communication with the Pico felt familiar because of how I had setup debug logging in the past. It looked like I had enough example repos collected that I could stitch a solution together. I did a little research each day and felt a little more sure each time. I've been using ChatGPT and Claude more and more to do initial research. I was at an AI hype peak and was bold enough to trust it...</p>
<p>
<br/>
<img src="https://nemo.foo/blog-content/deskthang/excalidraw.png" alt="" style="max-width:100%"/></p>
<p>Since I do full stack web stuff on the daily, the api, webhooks and postgres are out of scope for the degen day. I was scoping the day's work to Zig -&gt; Pico image transfer.</p>
<h3>1. Setup Pico</br>
</h3><ul>
<li>Organize the workspace</p>
</li>
<li>Find a micro usb cable that supports data and not just charging... really why are they all power only?!</p>
</li>
<li>Wire up a breadboard with Pico &amp; display and LED</p>
</li>
<li>Setup the C SDK for the raspi pico and a repo <a href="https://gitlab.com/nemofoo/deskthang">gitlab</a>, <a href="https://github.com/nemofoo/deskthang">gihub-mirror</a></p>
</li>
<li>Push a build and see logs on <code>cat /dev/ttyACM0</code></p>
</li>
</ul>
<p>
<br/>
<img src="https://nemo.foo/blog-content/deskthang/first_assembly.jpg" alt="" style="max-width:100%"/></p>
<h3>2. Setup Pico Display</br>
</h3><ul>
<li>Put something on the screen during the boot loop.</p>
</li>
</ul>
<p>
<br/>
<img src="https://nemo.foo/blog-content/deskthang/first_test_pattern.jpg" alt="" style="max-width:100%"/></p>
<p><a href="https://youtube.com/shorts/H6b64PJI40o">youtube link (12 sec)</a></p>
<h3>3. Setup Host Zig Project</br>
</h3><ul>
<li>Setup a host directory in repo</p>
</li>
<li>Init zig project</p>
</li>
<li>Send a message and see something on the screen</p>
</li>
</ul>
<p><a href="https://youtu.be/Y0wkzbwGWJc">youtube link (9 sec)</a></p>
<h3>4. Image Transfer</br>
</h3><ul>
<li>Yeet the raw rgb image data over USB</p>
</li>
<li>It's bidirectional safe right</p>
</li>
<li>USB CDC is bidirectional safe</p>

<ul>
<li>TTY interface is built on top of USB CDC</p>

<ul>
<li>TTY is bidirectional safe because CDC is (no it's not... thanks gpt)</p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>
<br/>
<img src="https://nemo.foo/blog-content/deskthang/gptlies.png" alt="" style="max-width:100%"/></p>
<blockquote>
<p>In the above image you can see the outright lie that broke me... USB CDC has separate TX (Transmit) and RX (Receive) buffers so it's bidirectional safe. The same is not true for TTY which is bidirectional but less safe with a single buffer for TX and RX data.</p>
</blockquote>
<br/><h2>Timeline of Actuality (AI Woes)</br>
</h2><p>After a dozen duds, I found a data capable usb micro cable and everything went smoothly until the image transfer. I used Claude, Cline, and ChatGPT to AI-max my way to a buggy but working implementation. I sent commands from my terminal with Zig over USB to the Pico which read them and changed the screen. This only took a few hours and I was excited that the AI assisted dream was real. It's not complex but I think it was faster than I could have done alone. I have no experience with zig besides hearing ThePrimeagen yap about it. I haven't even read the docs.</p>
<p>Multiple times, I found myself stopping Cline from starting completely new implementations of already solved issues. I didn't catch everything though. When Cline blew through my API limits, I added Claude to my harem and ran both in parallel when possible.</p>
<blockquote>
<p>As I look through the code now, I realize that I'm lousy at multitasking and was gaslighting myself.</p>
</blockquote>
<br/><h3>The Image Transfer Disaster</br>
</h3><p>This is where my hubris came into play. In my mind, I pictured sending all the image data in one go, like an S3 upload. I imagined clean, raw data streaming over <code>/dev/ttyACM0</code>. It wasn't clean. It wasn't raw. It was chaos.</p>
<p>I expected to see:</p>

<br/>
<pre><code>pico - heartbeat
zig - start image transfer
zig - [240x240 COLOR PIXELS]
zig - end image transfer
pico - heartbeat
</code></pre>
<br/><p>What I actually saw looked like this, but worse:</p>

<br/>
<pre><code>pico - heartbeat
zig - start ima%
pico - heage transfert
pico - heartbeat
zig - [240x240 COL
pico - heartbea
OR PIXELtS]
pico - heartbeat
zig - end image transfer
pico - heartbeat
</code></pre>
<br/><p><a href="https://youtu.be/jnmqlsdD6oU">It's just like that interrupting cow knock knock joke.</a> Completely unfunny and day ruining.</p>
<p><strong>Key Problems:</strong></p>
<p><strong>1. Buffer Conflicts:</strong> <code>/dev/ttyACM0</code> was the battlefield. The same buffer was used for both logging and image transfer. If a log slipped in during the data stream... well good luck figuring out what the hell just happened.</p>
<p><strong>2. Noise:</strong> Some weird corruption was happening. Maybe I wasn't clearing buffers properly. Maybe the gods of USB communication just hate me.</p>
<p>The bottom line? Neither the Pico nor my laptop could trust the data. Each system needed to learn to yield, and I needed to build the round-a-bout to force them to be polite and wait their turn.</p>
<h3>Packets, Protocols &amp; State Machines, Oh my...</br>
</h3><p>I needed to get serious. So, naturally, I let Claude write some docs:</p>
<ul>
<li>Detailed a packet shape.</p>
</li>
<li>Documented a checksum verification plan.</p>
</li>
<li>Described data format for transfer.</p>
</li>
<li>Denoted how to chunk and rebuild the image.</p>
</li>
<li>Depicted the state machine transitions.</p>
</li>
<li>Demonstrated command system.</p>
</li>
<li>Designed a logging system that doesn't break incoming commands.</p>
</li>
</ul>
<p>After delving down dem docs, I let AI run with the actual implementations. At this point, my &quot;degen hat&quot; came off, and I resumed my dad duties while letting Cursor and Cline play StarCraft with my codebase. This is the dream use case for AI, right? Just let it rip and come back to a perfectly functioning system. Let's see just how close we get to the sun.</p>
<p>Reality Check: AI tools are like interns who know how to Google really fast but don't understand context. Cursor started changing core implementations for unrelated edits. Cline would randomly rewrite half the system without asking. By the time I noticed, my codebase looked like the aftermath of a spaghetti fight at a junior developer convention. Most of the codebase was actually unreachable.</p>
<h2>What did I learn?</br>
</h2><p>Like Icarus, my codebase is irrecoverable. A tangled heap of wing fragments and melted wax, dripping with half-baked ideas and unsupervised AI chaos. My grand vision of outsourcing grunt work to AI had sent me soaring, but the sun of reality burned away any hope of landing gracefully. Here's what I'm taking away from this flaming descent.</p>
<h3>1. AI is a tool, not a co-pilot</br>
</h3><p>AI is great for generating ideas or drafting code, but it doesn't understand. It's like giving a junior developer a chainsaw instead of a scalpel—it might finish the job, but you'll spend twice as long cleaning up the mess. I learned that I need to stay firmly in the driver's seat when tackling new tech.</p>
<h3>2. Friction forces focus</br>
</h3><p>Having AI directly in my editor felt like playing with infinite cheat codes. It was too easy to let it run wild and harder to maintain control. Moving forward, I'm introducing deliberate friction. I will be using AI only in web interfaces or as a brainstorming tool. If I have to paste its suggestions into my code manually, I'll be more mindful of the process and less likely to reach for it.</p>
<h3>3. Mistakes teach better than shortcuts</br>
</h3><p>When I make mistakes, I learn. Debugging my own failures has always been one of the best ways to understand a new language or concept. Relying on AI to "fix" things for me short-circuited that learning process. As a result, I'm left with no deeper understanding of Zig than when I started.</p>
<h3>4. Patience beats hubris</br>
</h3><p>Building something new, with unfamiliar tools takes time. The idea that I could fully implement my vision in a single "degen day" was overly optimistic, bordering on foolish. Sometimes, you have to respect the complexity of what you're trying to achieve.</p>
<h2>Moving Forward</br>
</h2><p>Deskthang has grown from a casual afternoon project into a saga of overconfidence, AI misadventures, and lessons learned the hard way. For now, I'm shelving the AI driven shortcuts and committing to a rewrite on my next no-responsibilities day.</p>
<p>I've picked up a pen and started writing docs by hand like it's the stone age. I plan to work through some Advent of Code problems in Zig to actually learn the language before taking another crack at this project.</p>
<p>Want to see if Deskthang ever works, or just enjoy the chaos as I fail forward? Subscribe below for a monthly email drop of my latest misadventures and skill issues. Together, we'll learn how to coexist with AI, relearn the lessons I forget, and hopefully build something worthwhile in the process.</p>
<p>LFG 🚀</p>
]]></content:encoded>
        <category>blog</category>
      <category>rant</category>
      <category>deskthang</category>
      <category>ai</category>
    </item>
    

    <item>
        <title>DeskThang</title>
        <author>nemo</author>
        <link>https://nemo.foo/projects/deskthang</link>
        <pubDate>Sun, 26 Jan 2025 00:00:00 GMT</pubDate>
        <description><![CDATA[<p>A USB-connected desk companion that brings notifications into your workspace without the distractions of a phone or chat apps.</p>
]]></description>
        <content:encoded><![CDATA[<h2>DeskThang</br>
</h2><p>A USB-connected desk companion that helps maintain focus by bringing important notifications directly to your workspace, without the distractions of phones or chat apps.</p>
<h3>The Problems</br>
</h3><ol>
<li><strong>Notification Overload</strong>: Modern devices bombard us with notifications everywhere, making it difficult to maintain focus and separate work from personal life.</p>
</li>
<li><strong>Authentication Friction</strong>: Tools like GitLab's MFA, while necessary, create constant workflow interruptions.</p>
</li>
<li><strong>IoT Security Concerns</strong>: Traditional IoT devices with WiFi chips introduce unnecessary security risks and complexity.</p>
</li>
</ol>
<h3>The Solution</br>
</h3><p>DeskThang is a USB-connected device that:</p>
<ul>
<li>Features a 240x240 pixel circular LCD screen and programmable RGB LEDs</p>
</li>
<li>Connects via USB-C with no wireless components</p>
</li>
<li>Is completely scriptable through bash commands</p>
</li>
<li>Provides visual feedback for:</p>

<ul>
<li>CI/CD pipeline status</p>
</li>
<li>Payment notifications</p>
</li>
<li>System status indicators</p>
</li>
<li>Custom notifications</p>
</li>
<li>And more through simple scripting</p>
</li>
</ul>
</li>
</ul>
<h3>Technical Stack</br>
</h3><ul>
<li><strong>Host Driver</strong>: Written in Zig for efficient USB communication</p>
</li>
<li><strong>Firmware</strong>: C code running on the RP2040 (Raspberry Pi Pico)</p>
</li>
<li><strong>Scripting</strong>: Python for easy customization and integration</p>
</li>
<li><strong>Hardware</strong>:</p>

<ul>
<li>RP2040 microcontroller</p>
</li>
<li>240x240 circular LCD display</p>
</li>
<li>RGB LEDs</p>
</li>
<li>USB-C connection</p>
</li>
</ul>
</li>
</ul>
<h3>Design Philosophy</br>
</h3><ol>
<li><strong>Location-Based Computing</strong>: Notifications appear only where they're relevant - work notifications stay in the office.</p>
</li>
<li><strong>Security First</strong>: No wireless connectivity means fewer attack vectors and security concerns.</p>
</li>
<li><strong>Open Hardware</strong>: Complete documentation for firmware updates and hardware hacking included.</p>
</li>
<li><strong>Ultimate Scriptability</strong>: Simple bash commands enable endless customization possibilities.</p>
</li>
</ol>
<h3>Command Interface</br>
</h3><p>DeskThang provides a straightforward command-line interface:</p>

<br/>
<pre><code># Basic Commands
deskthang ping              # Send ping command (expects pong response)
deskthang test <1-4>       # Run test pattern 1-4
deskthang led <RRGGBB>     # Set LED color (hex format)
deskthang image path/to.png # Display image (240x240 png)
</code></pre>
<br/><p>These simple commands can be combined with other tools to create powerful automations. For example:</p>

<br/>
<pre><code># Turn LED red on failed GitLab pipeline
gitlab-ci-notifier on:failed "deskthang led FF0000"

# Display team logo during standups
at 9:00 "deskthang image ~/team-logo.png"
</code></pre>
<br/><h3>Project Status: Abandoned</br>
</h3><p><strong>This project has evolved into <a href="/projects/andon-lamp">Andon Lamp</a>.</strong></p>
<p>DeskThang served as the foundation for what became Andon Lamp - a refined, production-ready evolution of the original concept. While DeskThang focused on the core hardware and basic functionality, Andon Lamp represents the complete vision with improved software, better user experience, and a polished product offering.</p>
<p><strong>Key improvements in Andon Lamp:</strong></p>
<ul>
<li>Enhanced software architecture and reliability</p>
</li>
<li>Streamlined user experience and setup process</p>
</li>
<li>Production-ready hardware design</p>
</li>
<li>Comprehensive documentation and support</p>
</li>
<li>Active community and development</p>
</li>
</ul>
<p>Visit <a href="https://getandon.com">getandon.com</a> to learn more about Andon Lamp, or check out the <a href="/projects/andon-lamp">Andon Lamp project page</a> for technical details.</p>
<p><strong>Historical Development:</strong>
The original DeskThang development focused on:</p>
<ul>
<li>Implementing reliable USB communication protocols</p>
</li>
<li>Developing the state machine for robust data transfer</p>
</li>
<li>Creating a user-friendly command interface</p>
</li>
<li>Designing the initial PCB</p>
</li>
</ul>
<p>Follow the <a href="/blog/day-4-of-an-afternoon-project">development blog</a> for detailed insights into the challenges and progress that led to the creation of Andon Lamp.</p>
<h3>Demo Videos</br>
</h3><ul>
<li><a href="https://youtu.be/vBoUjOXry78">DeskThang Demo Video</a> - Watch DeskThang in action</p>
</li>
<li><a href="https://youtu.be/EQXRSVmZTXY">Wood Bending for DeskThang</a> - Exploring wooden enclosure possibilities</p>
</li>
<li><a href="https://youtu.be/XPz4_1GvufE">Cursor + DeskThang Integration</a> - See how DeskThang enhances the Cursor IDE experience</p>
</li>
</ul>
]]></content:encoded>
        <category>Hardware</category>
      <category>PCB</category>
      <category>Zig</category>
      <category>Embedded</category>
      <category>Electronics</category>
    </item>
    
    </channel>
</rss>