<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Chris Cantey</title>
    <link>https://chriscantey.com/</link>
    <description>Recent content on Chris Cantey</description>
    <image>
      <title>Chris Cantey</title>
      <url>https://chriscantey.com/img/og-default.png</url>
      <link>https://chriscantey.com/img/og-default.png</link>
    </image>
    <generator>Hugo -- 0.147.7</generator>
    <language>en-us</language>
    <lastBuildDate>Sat, 07 Mar 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://chriscantey.com/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Conference Notes with an AI Assistant</title>
      <link>https://chriscantey.com/posts/2026-03-07-conference-notes-ai/</link>
      <pubDate>Sat, 07 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://chriscantey.com/posts/2026-03-07-conference-notes-ai/</guid>
      <description>I tried something different at SCALE this year and brought my AI assistant along to capture, organize, and expand my notes throughout the day.</description>
      <content:encoded><![CDATA[<p>I very much love the massive mind melt of new information that I get when I attend great tech conferences. But I&rsquo;ve never been super good at keeping notes thorough enough to remember everything I want to, or follow up on all the new tech and links I had aspirations to while sitting in the rooms.</p>
<p>The talks I really liked? I remember them well enough to tell someone about them over coffee, but the specific details, the links the speaker mentioned, the names of tools that came up in Q&amp;A, those are usually gone by the time I get home. I end up with a few half-sentences scratched into my phone&rsquo;s Notes app and a vague impression of &ldquo;yeah, good stuff.&rdquo;</p>
<p>This week I&rsquo;m trying something different at <a href="https://www.socallinuxexpo.org/scale/23x" target="_blank" rel="noopener noreferrer">SCALE 23x</a>
 in Pasadena: I brought my AI assistant along.</p>
<h2 id="the-setup">The Setup</h2>
<figure style="max-width: 320px; margin: 1.5em auto;">
<img src="/img/posts/conference-phone-terminal-v2.jpg" alt="Claude Code + PAI running on my phone over SSH at the conference" style="width: 100%; border-radius: 8px;">
</figure>
<p>I run Claude Code + <a href="https://github.com/danielmiessler/Personal_AI_Infrastructure" target="_blank" rel="noopener noreferrer">PAI</a>
 on a dedicated Linux VM at home (<a href="https://chriscantey.com/posts/2026-02-02-setting-up-your-personal-ai-assistant/">see my setup here</a>
). It&rsquo;s a persistent system. My assistant has memory, skills, tools, and context about my work and projects. I usually work with it through a terminal, either at my desk or from my phone over SSH. The conference was no different.</p>
<p>The connection is straightforward. I use <a href="https://tailscale.com/" target="_blank" rel="noopener noreferrer">Tailscale</a>
 to connect my devices into my home lab network, so I can reach my server from anywhere. On my iPhone I use an SSH client to connect directly into the VM and start a Claude Code session. Same assistant, same context, same tools, just on a smaller screen.</p>
<p><img alt="Conference note-taking workflow: Phone connects via Tailscale and SSH to AI Assistant, which produces organized notes, research, and audio reports" loading="lazy" src="/img/posts/conference-workflow-01.jpg"></p>
<p>Before the first talk, I gave it a detailed briefing: Here&rsquo;s what the day looks like. Here&rsquo;s the conference. Here&rsquo;s the schedule from the website. Go scrape the schedule page. If it&rsquo;s JavaScript-heavy and hard to parse, use your browser skill to render it first. Throughout the day, I&rsquo;m going to dump raw notes to you. Track which talk I&rsquo;m probably in based on the time. Expand any links I mention. Follow up on brief references. If I flag something for research, dig into it. Tag anything that looks like a future task. And when I tell you the day is done, build me a full report.</p>
<h2 id="throughout-the-day">Throughout the Day</h2>
<p>The workflow settled into a rhythm pretty quickly. Between talks, or during slower moments, I&rsquo;d SSH in and dump whatever was on my mind. Sometimes it was a direct quote from a speaker, sometimes a half-formed thought triggered by something someone said, and sometimes just a link I saw on a slide that I wanted to remember.</p>
<p>I let the assistant decide how to organize everything within the structure of my existing system. It roughly did this: every note went into a raw file first, timestamped and verbatim. From there, it triaged each piece. Facts, tools, and contact info went into a knowledge file. Things I wanted to expand on later got queued for deeper reports. The schedule tracking meant it could attach context to my notes automatically. If I dropped a note at 2:45 PM, it knew I was probably in the decentralized trust talk and could frame my notes accordingly.</p>
<p>The other nice thing is that it can ask me for clarity in real time. If I drop a vague note and the assistant needs more context, it asks while the thought is still fresh. That back-and-forth means the notes get augmented properly instead of sitting there as cryptic fragments I&rsquo;ll have to decode later. And in some rather awesome cases, it was tracking context of time and event and talk description well enough that it was able to figure it out on its own. Very pleasing :)</p>
<p><img alt="A slide from the vector database benchmarking talk at SCALE" loading="lazy" src="/img/posts/conference-slide-photo.jpg"></p>
<p>Slide capture was also fun. When a speaker put up something worth keeping, I&rsquo;d take a photo and upload it through an <a href="https://chriscantey.com/posts/2026-02-02-setting-up-your-personal-ai-assistant/">exchange portal</a>
 I have set up on the server. The assistant watches for incoming images, pulls text from them, and starts working with whatever&rsquo;s on the slide. During the vector database benchmarking talk, I uploaded a series of comparison slides and had the key findings extracted and organized before the speaker moved on to Q&amp;A.</p>
<p>Links got the same treatment. If a speaker mentioned a project or a tool, I&rsquo;d jot down the name and the assistant would go find it, grab the URL, pull in whatever context was available, and add it to the knowledge file.</p>
<h2 id="the-end-of-day-report">The End-of-Day Report</h2>
<p>At the end of the day, I told the assistant we were done and asked it to build the report. It compiled everything: talk summaries with expanded context, all the links it had gathered, slide content it had processed, research it had done on topics I&rsquo;d flagged, and a follow-up list of things to look into later. The report went to a <a href="https://chriscantey.com/posts/2026-02-02-setting-up-your-personal-ai-assistant/">portal page</a>
 I could review at my leisure, and I also had it send the content to <a href="https://github.com/chriscantey/hypercast" target="_blank" rel="noopener noreferrer">Hypercast</a>
, a personal TTS-to-podcast service I run, so I could listen back to it as audio later.</p>
<p><img alt="The end-of-day conference report compiled by the assistant" loading="lazy" src="/img/posts/conference-report.jpg"></p>
<p>The report was significantly more detailed than anything I would have produced on my own. Not because the assistant made things up, but because it had been doing background work all day while I was focused on the talks.</p>
<h2 id="what-worked">What Worked</h2>
<p>The biggest win was that I could stay present. Instead of trying to capture everything in the moment and losing attention on the speaker, I could drop a few words and trust that the context would be filled in later. A note like &ldquo;Rivest, homomorphic encryption, 1970s, dig into this&rdquo; became a full entry with the history of the concept, the 2009 breakthrough by Craig Gentry, why it&rsquo;s still not computationally practical, and how it connects to the confidential vector search work being presented. That kind of expansion happened across every note I flagged for research.</p>
<h2 id="the-friction">The Friction</h2>
<p>Typing on a phone through an SSH client is not ideal. It works, but it&rsquo;s slow, and the screen is small enough that you have to be deliberate about what you type. I found myself keeping notes shorter than I might have at a keyboard, which was fine for the workflow but occasionally meant I left out context that would have helped. A laptop would make this easier and faster since the entire workflow is the same, just SSH into the server and go. I just don&rsquo;t love pulling out a laptop in crowded conference rooms and tip-tapping away on my keyboard when I can avoid it.</p>
<p>Privacy was a consideration. I was typing into a terminal in a conference hall full of people, some of whom could see my screen. I added &ldquo;buy a privacy screen protector&rdquo; to my follow-up list pretty early in the day.</p>
<p>Conference WiFi is notoriously slow and inconsistent (why are conference venues always faraday cages?), but Tailscale kept me connected well, and I could use Tmux on the server to reconnect to my session if my WiFi or cellular dropped.</p>
<p>I use voice with my assistant all the time at home, but at a conference you&rsquo;re stuck typing. What I&rsquo;d really like is a proper chat interface for my assistant that doesn&rsquo;t lose all of my context, tools, and systems the way something like the Claude.ai app would. Claude Code&rsquo;s remote control feature isn&rsquo;t quite reliable enough for this yet, but I&rsquo;m sure we&rsquo;ll have a smoother way to do this in a week or a month. More on that later.</p>
<h2 id="where-this-goes">Where This Goes</h2>
<p>I&rsquo;m not sure how novel any of this is. People have been using chatbot apps for note-taking for a while. The difference for me is that the assistant isn&rsquo;t a blank chat window. It&rsquo;s a persistent system with context about my work, my projects, and what I care about, and it can act on notes rather than just store them.</p>
<p>I&rsquo;m still in the middle of the conference as I write this, and I&rsquo;ll keep refining the workflow over the remaining days. For now, the phone-and-SSH approach is getting the job done better than my usual strategy of hoping I&rsquo;ll remember things later.</p>
<p>If you&rsquo;re curious about the personal AI setup behind this, I wrote about it <a href="https://chriscantey.com/posts/2026-02-02-setting-up-your-personal-ai-assistant/">here</a>
. And the end-of-day reports live on <a href="https://github.com/chriscantey/hypercast" target="_blank" rel="noopener noreferrer">Hypercast</a>
.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Build Notes</title>
      <link>https://chriscantey.com/posts/2026-03-06-build-notes/</link>
      <pubDate>Fri, 06 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://chriscantey.com/posts/2026-03-06-build-notes/</guid>
      <description>How I&amp;#39;m sharing project write-ups that sit somewhere between a README and a full codebase (that you can give an AI assistant!)</description>
      <content:encoded><![CDATA[<p>I&rsquo;ve been trying to figure out a good way to share how I&rsquo;ve built some of my projects. People ask about them, and I usually end up walking through the same explanation a few different times in different conversations. Sometimes I&rsquo;ll share a repo, but that&rsquo;s often either too much or not enough. The code is there, but the context around it isn&rsquo;t. Why I chose one approach over another, what I tried first, the tradeoffs I made along the way.</p>
<p>In <a href="/posts/2026-02-24-build-or-buy-may-have-changed/">Build or Buy May Have Changed</a>
 I talked about how the cost of building custom tools has dropped to where more people can realistically build their own versions of things. Near the end of that article I mentioned that the write-up itself could be a starting point for someone&rsquo;s assistant to help them build something like it. That idea kept pulling at me. If someone&rsquo;s assistant can read a description of how something works and help them build their own version, what&rsquo;s the right format for that description?</p>
<p>It&rsquo;s somewhere between a README and a full codebase. Not a spec, and not really documentation in the traditional sense either. More like a write-up from one builder to another, or from one assistant to another. For now, I&rsquo;m calling them build notes. I could see these eventually becoming part of a more structured system design document or something like that, but right now they&rsquo;re just practical descriptions of things I&rsquo;ve built.</p>
<p>Each note covers what the thing does, why I built it that way, how the pieces connect, and the key decisions with their tradeoffs. There&rsquo;s reference code included, but they&rsquo;re not full codebases and they&rsquo;re not install scripts. They&rsquo;re closer to showing a friend how you wired something up in your garage, with enough detail that they could go build their own version.</p>
<p>Each note also has a short &ldquo;for AI assistants&rdquo; section near the top. If you point your assistant at one of these and say &ldquo;help me build something like this,&rdquo; it should have enough to work with. That was the main thing I wanted to get right.</p>
<h2 id="the-first-three">The first three</h2>
<p><strong>Mac Services API</strong> is how I give my assistant access to my Mac&rsquo;s Calendar, Reminders, and Contacts without running the assistant on the Mac itself. It&rsquo;s a REST API that the assistant calls over the network.</p>
<p><strong>Notes Inbox</strong> is a capture workflow. I press a button on my iPhone, say what&rsquo;s on my mind, and it shows up in my assistant&rsquo;s inbox immediately. An Apple Shortcut handles the dictation and sends it to a small API server exposed through a Cloudflare Tunnel.</p>
<p><strong>Hugo Blog</strong> covers this blog&rsquo;s setup. Hugo with PaperMod, Cloudflare Pages for hosting, and optionally a Cloudflare Worker for newsletter subscriptions. The hosting costs me nothing.</p>
<p>I&rsquo;ll keep adding more as I write them up. Some of the things in my setup are more involved than these first three, so the depth will vary.</p>
<p>Everything is at <a href="https://github.com/chriscantey/build-notes" target="_blank" rel="noopener noreferrer">github.com/chriscantey/build-notes</a>
.</p>
]]></content:encoded>
    </item>
    <item>
      <title>A Knowledge Base for Your AI Assistant</title>
      <link>https://chriscantey.com/posts/2026-03-02-a-knowledge-base-for-your-ai-assistant/</link>
      <pubDate>Mon, 02 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://chriscantey.com/posts/2026-03-02-a-knowledge-base-for-your-ai-assistant/</guid>
      <description>I moved my notes from Obsidian into a knowledge base my AI assistant can search and maintain. Here&amp;#39;s what that looks like and how to try it.</description>
      <content:encoded><![CDATA[<p>I used Obsidian for years and loved it. Still do. It&rsquo;s a great app, and if you&rsquo;re using it, I&rsquo;m not here to talk you out of it. But something shifted for me over the past few months as I started doing more and more of my work through my AI assistant. I found myself spending less time in Obsidian&rsquo;s UI and more time just working with documents directly through Claude Code. The notes were still there, but I was reaching for them less because I was already in the terminal.</p>
<p>About a month ago I decided to try something. After backing up my Obsidian directories, I asked my assistant to ingest everything into a structured knowledge base it could search and maintain. I figured if it didn&rsquo;t work out, I could always go back. So far I haven&rsquo;t looked back.</p>
<p>I&rsquo;m not declaring Obsidian or local markdown apps over for me. I might go back. But for the moment, I&rsquo;m enjoying having my assistant as the primary interface to my notes, with a few layers underneath to make sure I&rsquo;m not locked in.</p>
<h2 id="what-it-is">What It Is</h2>
<p>This isn&rsquo;t a replacement for Claude Code&rsquo;s built-in memory or PAI&rsquo;s memory system. Those are getting better over time, and they serve a different purpose. Claude Code&rsquo;s memory captures patterns and preferences automatically. This is something more intentional. A persistent knowledge store that I control directly, that survives across Claude Code sessions and PAI upgrades, and that I can add to, search, and browse whenever I need to.</p>
<p>Think of it as a personal reference library. The assistant helps you store things, find things, and use what&rsquo;s there. But the files are just markdown in folders on your system. If the assistant isn&rsquo;t available, you still have the files.</p>
<h2 id="how-it-works">How It Works</h2>
<p>The Knowledge skill gives your Claude Code assistant three workflows: learn, recall, and browse.</p>
<p><strong>Learn</strong> is how information gets in. When I come across something I want stored, I just say &ldquo;remember this&rdquo; or &ldquo;save this&rdquo; and describe what I want. The assistant creates a structured markdown entry, files it under a category, and updates an index. No database, no proprietary format. Plain text, organized by topic.</p>
<p>For example, I might say &ldquo;remember that my Bambu Lab A1 uses a 0.4mm nozzle and I usually print PLA at 220 degrees.&rdquo; That becomes an entry under <code>tech</code> with a title, tags, and the full details. Next time 3D printing comes up, the assistant already has my setup.</p>
<p><strong>Recall</strong> is how information comes back. When I ask &ldquo;what do I know about my printer settings&rdquo; or &ldquo;how do I connect to the office VPN,&rdquo; the assistant searches the index first by title and tags, without reading every file. If it finds matches, it loads the specific entries and gives me the answer. Index-first search keeps it fast even as the knowledge base grows.</p>
<p><strong>Browse</strong> gives me an overview. I can say &ldquo;show my knowledge base&rdquo; and see everything organized by category, or drill into a specific area. Useful for seeing what&rsquo;s accumulated and whether anything needs updating.</p>
<h2 id="a-few-ways-i-use-it">A Few Ways I Use It</h2>
<p><strong>Technical reference.</strong> Configuration details for servers, network equipment, and services. When I need to remember which port something runs on or what the correct mount path is, the assistant looks it up instead of me digging through config files. Especially helpful for things I set up months ago and don&rsquo;t touch often enough to keep the details in my head.</p>
<p><strong>Project context.</strong> When I&rsquo;m working on something over multiple sessions, I&rsquo;ll have the assistant save key decisions and the reasoning behind them. &ldquo;Remember that we chose Hono over Express for this worker because of the Cloudflare bindings support.&rdquo; Two weeks later when I&rsquo;m back in that project, the context is there without me having to re-explain the whole history.</p>
<p><strong>Personal information.</strong> Preferences, dimensions for home projects, product model numbers. The assistant knowing that my office desk is 60 inches wide and my monitor arm clamp maxes out at 2.5 inches thick has been useful more than once. It&rsquo;s the kind of information that doesn&rsquo;t fit neatly into any other system.</p>
<p><strong>Work patterns.</strong> Procedural knowledge. How I like security reports formatted. The steps for a specific compliance workflow. The assistant can reference these patterns and apply them without me repeating myself. I wrote more about this kind of thing in <a href="/posts/2026-02-24-build-or-buy-may-have-changed/">Build or Buy May Have Changed</a>
, where the bigger idea is that your assistant can take a reference like this and build something tuned to how you actually think and work.</p>
<h2 id="multiple-ways-in">Multiple Ways In</h2>
<p>One thing I wanted to get right was making sure I&rsquo;m not dependent on any single interface to reach my notes. Right now I have a few paths to the same data:</p>
<p>The assistant itself is the primary interface. The skill handles ongoing capture, search, and retrieval through conversation. That&rsquo;s how I interact with it most of the time.</p>
<p>There&rsquo;s also a web UI for browsing and searching entries visually. It&rsquo;s optional and not required for the skill to work. If you already have <a href="/posts/2026-02-14-pai-companion/">PAI Companion</a>
 running, the UI drops right into your existing portal. Otherwise it can run standalone in Docker.</p>
<p><img alt="The knowledge base web UI showing categories, search, and entry list" loading="lazy" src="/img/posts/knowledge-skill-browse-ui.png"></p>
<p>I also built a markdown editor that runs in the browser. It&rsquo;s the closest I&rsquo;ve come to the markdown editing experience I&rsquo;ve always wanted, and it&rsquo;s included in the repo in an early form. Handy for cleaning up or expanding entries when you&rsquo;d rather just edit directly.</p>
<p><img alt="The markdown editor with tabbed documents and a formatting toolbar" loading="lazy" src="/img/posts/knowledge-skill-editor.png"></p>
<p>And if none of those are available, if the UI service is down or Claude is having an outage, the files are still just markdown on the file system. You can open them in any editor. That was intentional.</p>
<h2 id="a-note-on-backups">A Note on Backups</h2>
<p>Moving my notes into this system means my knowledge base now lives inside my Claude Code and PAI environment. That&rsquo;s a different risk profile than files synced through iCloud or sitting in a local Obsidian vault. It&rsquo;s worth thinking about. The data is still just files on disk, so any backup strategy that covers that directory works. But it does need to be part of the plan.</p>
<h2 id="try-it">Try It</h2>
<p>The Knowledge skill works with <a href="https://docs.anthropic.com/en/docs/claude-code" target="_blank" rel="noopener noreferrer">Claude Code</a>
, <a href="https://github.com/danielmiessler/PAI" target="_blank" rel="noopener noreferrer">PAI</a>
, and <a href="https://github.com/chriscantey/pai-companion" target="_blank" rel="noopener noreferrer">PAI Companion</a>
.</p>
<p>Head over to the repo for <a href="https://github.com/chriscantey/skill-knowledge" target="_blank" rel="noopener noreferrer">the Knowledge skill.</a>
</p>
<p>If you&rsquo;re using PAI (<a href="/posts/2026-02-14-pai-companion/">here&rsquo;s my setup</a>
), the quick install is:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#8be9fd;font-style:italic">cd</span> ~ <span style="color:#ff79c6">&amp;&amp;</span> git clone https://github.com/chriscantey/skill-knowledge.git
</span></span></code></pre></div><p>Then tell your assistant:</p>
<pre tabindex="0"><code>Read ~/skill-knowledge/INSTALL.md and follow its instructions.
</code></pre><p>It&rsquo;ll walk you through setup, ask if you want the web UI, and handle everything from there. Manual install instructions are in the repo if you&rsquo;d rather do it yourself.</p>
<h2 id="its-a-starting-point">It&rsquo;s a Starting Point</h2>
<p>Like the <a href="/posts/2026-02-17-ai-assisted-3d-printing/">3D printing skill</a>
 I shared earlier, this is an export from my system, not a packaged product. It reflects how I think about organizing information, which may not be how you think about it. The categories I use (tech, home, health, finance, work) are just defaults. Your assistant can create new ones as needed.</p>
<p>The more interesting thing is that your assistant can take this as a reference and build something better. Maybe you want different categories. Maybe you want entries that expire or get flagged for review after a certain period. Maybe you want your knowledge base to integrate with something else entirely. The skill is simple enough that adapting it is straightforward.</p>
<p>I&rsquo;d love to hear what people do with it. If you build on it and learn something, sharing back is always appreciated.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Upgrading PAI from v3 to v4</title>
      <link>https://chriscantey.com/posts/2026-03-01-upgrading-pai-from-v3-to-v4/</link>
      <pubDate>Sun, 01 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://chriscantey.com/posts/2026-03-01-upgrading-pai-from-v3-to-v4/</guid>
      <description>An AI-driven upgrade script that migrates your PAI installation from v3 to v4 without losing your customizations.</description>
      <content:encoded><![CDATA[<div style="background: rgba(18, 194, 233, 0.1); border-left: 3px solid #12c2e9; padding: 1rem; border-radius: 0 6px 6px 0; margin: 1.5rem 0;">
  <strong>Just want the upgrade command?</strong> <a href="#before-you-start">Skip to Run the Upgrade.</a>
</div>
<p>A quick note before we get into it: this is not the official PAI upgrade path. Daniel Miessler&rsquo;s recommended approach is to clone the latest release fresh, back up your <code>~/.claude/</code> directory, overwrite it with the new version, and then bring your customizations back in. That works. I&rsquo;ve done it.</p>
<p>What I&rsquo;ve found works more consistently for me, though, is having my assistant do the migration itself. It&rsquo;s aware of what changed between versions, it knows where your files need to move, and it can verify each step as it goes. The tricky part is getting the commands, the workflow, and the patterns right, which is why I&rsquo;ve written this guide and the upgrade script that goes with it. It&rsquo;s an attempt to package what I&rsquo;ve learned doing these upgrades so other people&rsquo;s assistants should be able to do the same thing.</p>
<p>That said, always back up first. If you don&rsquo;t like what the upgrade did, you should be able to roll back. The script creates a backup for you, but a VM snapshot is even better if you have that option.</p>
<h2 id="what-changed">What Changed</h2>
<p>Daniel describes v4 as <a href="https://github.com/danielmiessler/Personal_AI_Infrastructure/releases/tag/v4.0.0" target="_blank" rel="noopener noreferrer">&ldquo;Lean and Mean&rdquo;</a>
: 38 flat skill directories compressed into 12 hierarchical categories, dead systems removed, context footprint cut in half.</p>
<p>The biggest shift is organizational. In v3, everything lived in a flat structure. Skills, hooks, your custom stuff, PAI&rsquo;s built-in stuff, all mixed together in the same directories. v4 introduces clear boundaries.</p>
<p><strong>Skills got reorganized.</strong> 38 flat skill directories became 12 hierarchical categories (Research, Media, Thinking, Security, etc.) with around 63 skills total. Your custom skills move to a dedicated <code>skills/Custom/</code> folder, so PAI updates never accidentally overwrite your work.</p>
<p><strong>CLAUDE.md is now generated.</strong> Instead of one big hand-edited file that grew over time, v4 uses a template system. Your personal configuration lives in dedicated files under <code>PAI/USER/</code>, and a build tool generates a clean CLAUDE.md from them. This keeps things maintainable as both PAI and your customizations evolve.</p>
<p><strong>New PAI directory.</strong> v4 adds a <code>PAI/</code> directory for system documentation, tools, and user context. The <code>PAI/USER/</code> subdirectory is where your identity, preferences, and project context now live. It&rsquo;s explicitly portable across upgrades.</p>
<p><strong>Context footprint dropped.</strong> Daniel&rsquo;s release notes say startup context went from ~38% to ~19%. That means more of Claude&rsquo;s attention goes to your actual work instead of system overhead.</p>
<h2 id="what-gets-preserved">What Gets Preserved</h2>
<p>Everything you&rsquo;ve built should come with you:</p>
<ul>
<li>Your custom skills (relocated to <code>skills/Custom/</code>)</li>
<li>Your steering rules and identity settings (migrated to <code>PAI/USER/</code>)</li>
<li>Your memory, sessions, and learning data</li>
<li>Any custom hooks you&rsquo;ve added</li>
</ul>
<p>The file layout changes, but your content is preserved.</p>
<h2 id="before-you-start">Before You Start</h2>
<p>If you&rsquo;re running PAI in a VM and your hypervisor supports snapshots or clones, take one now. The upgrade tool creates its own backup, but having a full VM snapshot means you can roll back the entire machine if anything unexpected happens. It takes a minute and it&rsquo;s the best safety net you can have.</p>
<h2 id="run-the-upgrade">Run the Upgrade</h2>
<p><strong>If you&rsquo;re already using <a href="https://github.com/chriscantey/pai-companion" target="_blank" rel="noopener noreferrer">PAI Companion</a>
:</strong> Tell your assistant to pull the latest changes and run the upgrade:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>Pull the latest PAI Companion changes, then read ~/pai-companion/upgrade/UPGRADE.md and follow the upgrade phases.
</span></span></code></pre></div><p><strong>If you&rsquo;re not using PAI Companion</strong> and just want to upgrade PAI to v4, your assistant can read the upgrade guide directly from GitHub without cloning anything:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>Fetch and read https://raw.githubusercontent.com/chriscantey/pai-companion/main/upgrade/UPGRADE.md and follow the upgrade phases.
</span></span></code></pre></div><p>Either way, the tool should detect your version, back everything up, and walk through each phase.</p>
<p>When it&rsquo;s done, exit PAI / Claude Code. Run this before you relaunch:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#8be9fd;font-style:italic">source</span> ~/.bashrc
</span></span></code></pre></div><p>If you run into any errors after the upgrade, most of them should be resolvable by logging completely out of your VM, logging back in, and starting a fresh Claude Code session.</p>
<p>If you&rsquo;re doing a fresh install instead of upgrading, the <a href="/posts/2026-02-02-setting-up-your-personal-ai-assistant/">setup guide</a>
 and <a href="/posts/2026-02-14-pai-companion/">companion post</a>
 cover that path.</p>
<hr>
<p><em>Part of the <a href="/tags/pai-setup/">PAI Setup Series.</a>
 Previous: <a href="/posts/2026-02-24-build-or-buy-may-have-changed/">Build or Buy May Have Changed</a>
</em></p>
]]></content:encoded>
    </item>
    <item>
      <title>Build or Buy May Have Changed, For Now</title>
      <link>https://chriscantey.com/posts/2026-02-24-build-or-buy-may-have-changed/</link>
      <pubDate>Tue, 24 Feb 2026 00:00:00 +0000</pubDate>
      <guid>https://chriscantey.com/posts/2026-02-24-build-or-buy-may-have-changed/</guid>
      <description>A Mac app I relied on shut down. So I built my own replacement. It made me look at how our relationship with software might be shifting.</description>
      <content:encoded><![CDATA[<p>Earlier this year, MacUpdater shut down after eight years. If you&rsquo;re not familiar, it was a Mac utility that helped you track, manage, and install updates across all of your applications. It maintained a database of over 150,000 apps, scanned your Mac against it, and kept you aware of what needed attention. The team behind it had been selling one-year licenses, and after struggling to find a sustainable business model, they decided not to continue.</p>
<p>I&rsquo;d been relying on it for years. My first instinct was to look for a replacement. That&rsquo;s how it&rsquo;s always worked. A tool goes away, you find the next one, you pay the subscription or the one-time fee, and you move on.</p>
<p>But this time I did something different. I built my own.</p>
<h2 id="update-monitor">Update Monitor</h2>
<p>Not as a product. Not to sell. Just for me. I built a small system I&rsquo;ve been calling Update Monitor. There&rsquo;s a lightweight component on each of my Macs that scans what&rsquo;s installed and sends the catalog up to a central service. That service maintains a list of all the software sources my Macs report in on and checks for the latest versions. It classifies updates as low priority or critical based on my own priorities and known sensitivities of things like browsers and other internet-connected software. It tracks published security updates and known vulnerabilities. And it reports back to me when something needs my attention.</p>
<p><img alt="Update Monitor showing summary stats and critical updates for Firefox and Chrome" loading="lazy" src="/img/posts/build-or-buy/update-monitor.jpg"></p>
<p>The whole thing took a few focused sessions with my AI assistant. Maybe an hour before we had something functional, then a few more sessions over the following days to refine it. And it actually works better for me than the commercial product did.</p>
<p>I can mark my own severity levels. I can hunt down sources for more obscure software that a commercial database might not cover well. The system is tuned to how I think about risk, not how a product thinks I should.</p>
<p>Even more than that, though. I appreciated MacUpdater, and I ultimately decided to trust it, but I never loved that I was scanning all of my apps daily and sending that data out to a company that was hard to find details about. That was the trade: they maintained the database and the Mac software, and in exchange I sent them a complete picture of everything installed on my machines.</p>
<p>With Update Monitor, I was able to shift that model. The scan on my computer is as lightweight as I can make it, keeping the footprint on my machines low. The data goes to my own service, which in my case runs as part of my <a href="/posts/2026-02-14-pai-companion/">AI assistant infrastructure</a>
. It didn&rsquo;t have to be set up that way. It could have been a standalone service. I tie it in because the assistant helps me prioritize updates in the context of other things I&rsquo;m working on, and it&rsquo;s been useful for hunting down and maintaining the sources.</p>
<p>That was one of the components that made MacUpdater challenging to sustain. Their team maintained a config file with tens of thousands of app entries and a version database with millions of records. They wrote that the daily maintenance took more than a full day to perform, even with a trained team. My list is a lot smaller, and it&rsquo;s just for me. With the assistant handling most of the source maintenance, I mostly just need to make sure the sources don&rsquo;t change on me, and I even have it watching for that. Day to day, the scanning and reporting is deterministic.</p>
<p>For someone who thinks about trust and supply chain risks professionally, all of that adds up.</p>
<h2 id="its-not-just-one-tool">It&rsquo;s Not Just One Tool</h2>
<p>It&rsquo;s interesting to step back and look at just how much custom software has found its way into my life and workflow, especially over the last few months. Dashboards for tracking projects and compliance. Monitors for services and system health. An assistant infrastructure with skills I&rsquo;ve built for specific workflows. Media production tooling. Content pipelines. A personal podcast system that turns articles into audio. Gaming tools for friends. Security tools I run on my own network.</p>
<p><img alt="A glowing neon hand with small luminous objects orbiting above it like a personal ecosystem" loading="lazy" src="/img/posts/build-or-buy/orbit.jpg"></p>
<p>None of these are products. None of them are on the app store. They&rsquo;re things I built because I needed them, and the AI tools made the building fast enough that it was worth doing.</p>
<p>This isn&rsquo;t just me, either. Build or buy is in the news right now because investors are watching SaaS companies and wondering what it means for their growth when more people can build their own tools. Stock prices are reacting. There&rsquo;s a big conversation about whether the economics of software subscriptions are shifting.</p>
<p>I think there&rsquo;s some truth to that, but also likely some overcorrection. A colleague recently pointed out that a lot of what makes large SaaS products viable isn&rsquo;t just the software itself. It&rsquo;s the compliance certifications, the liability and insurance, the support infrastructure, the years of security hardening. Millions of companies are not going to stop using their existing tools. And for software that stores large amounts of sensitive data, like communication platforms, file sharing services, or anything customer-facing, the security requirements alone are significant. That&rsquo;s very unlikely to totally go away.</p>
<p>But for a growing number of people and a growing range of use cases, the cost of building something custom has dropped to the point where it makes sense. Not for everything. But for more things than it used to.</p>
<h2 id="the-shift">The Shift</h2>
<p>A year ago, building something custom meant either learning enough to write it yourself, which could take weeks or months or much longer depending on the project, or hiring someone, which can cost quite a bit of money. The time and expense were enough that buying a SaaS product was almost always the smarter choice, even if it didn&rsquo;t fit perfectly.</p>
<p>But that&rsquo;s changing. I&rsquo;ve had similar experiences with clients recently. We&rsquo;ve had projects that benefit from visualizing massive amounts of interconnected information, the kind of thing where we would have had to rely on sophisticated pre-built systems or worse, in some cases, just spreadsheets. Being able to build something custom let us take approaches that were far more effective. The features, the usability, the ability to shape the tool around the actual problem instead of the other way around. We built something in about three days that delivered more value than tools we&rsquo;d been paying for and not getting half the return from.</p>
<p>Would it need to be maintained if it runs long term? Yes. But the initial investment was small enough, and the return immediate enough, that it shifts how you think about the decision.</p>
<p>There&rsquo;s something else happening too. The software can adapt to you instead of you adapting to it. Especially in use cases like mine, where it&rsquo;s a one-to-one relationship between me and the tool, that lowers a lot of the friction. I don&rsquo;t have to learn a whole new system. I don&rsquo;t have to deal with a major version update from a vendor that rearranges everything. I can make changes when I want to, at the pace I want to.</p>
<p>In a lot of these cases, the tools are more like reports than applications. You use them, and when the need changes, you build something new. The software is more ephemeral. In these cases, not every tool needs to be a product with a roadmap and a changelog.</p>
<h2 id="why-im-not-releasing-this-as-a-product">Why I&rsquo;m Not Releasing This as a Product</h2>
<p>The thought has crossed my mind. Update Monitor works well. Other people might want something like it, especially now that MacUpdater is gone.</p>
<p>But the moment you start thinking about making something available to others, the requirements multiply. Take the update tracker as an example. Maintaining a version database for everyone&rsquo;s applications, not just the ones on my machines, is a massive undertaking. It&rsquo;s one of the reasons the MacUpdater team shut down. They couldn&rsquo;t make the economics work, and the daily effort of maintaining that database was enormous.</p>
<p>And the database is only part of it. Then you need to maintain a client application that works across multiple versions of macOS, on different hardware. You need testing. You need support. You need a server that hosts the database, and with people connecting to that server, you need to protect and monitor that server, keep it updated, and maintain compatibility across all your client versions at the server level.</p>
<p><img alt="A single glowing neon spark at center exploding outward into fractal branches and tendrils" loading="lazy" src="/img/posts/build-or-buy/fractal.jpg"></p>
<p>Then there&rsquo;s the trust chain. If it&rsquo;s just for me, I trust the sources I&rsquo;m picking. I trust the code because I&rsquo;m reviewing it as I go and testing it as I go. If I ship it to others, now they need to trust me. And I need to trust a wider set of sources, automations, and people. The responsibility grows in every direction.</p>
<p>It goes from being my tool to being a product. That&rsquo;s a different game entirely. For a long time, we&rsquo;ve just had to accept trust chains as they were because there was really only one way to get software: someone else built it and you decided whether to trust them. Now there&rsquo;s another option, and that changes the equation.</p>
<h2 id="others-can-build-their-own">Others Can Build Their Own</h2>
<p>Here&rsquo;s what interests me, though. I don&rsquo;t need to release it as a product for other people to benefit from the idea. This article itself could be a starting point for someone&rsquo;s assistant to help them build something like it. It won&rsquo;t be identical to mine, and that&rsquo;s fine. It&rsquo;ll be tuned to their needs, their priorities, their threat model.</p>
<p>Maybe not everybody can do this at this moment. But more people can than could a few years ago. More people will be able to next month, next year. The barrier keeps dropping, and it seems to be dropping fast. Tools and projects that were only accessible to experienced developers are now within reach of people who can describe clearly what they want and think through how it should work. That seems to be the real factor right now. The building part has gotten dramatically easier. The harder part is being able to visualize what you need, describe it well, and keep it organized as you go.</p>
<p><img alt="A glowing neon dandelion with seeds drifting away into the darkness, each seed a tiny point of light" loading="lazy" src="/img/posts/build-or-buy/dandelion.jpg"></p>
<p>There&rsquo;s also a case for sharing, but maybe not in the way we&rsquo;re used to. If a lot of people are independently having AI build roughly the same kind of tool, that does feel redundant. Repeated work, repeated compute, repeated time solving problems that have already been solved. But the sharing doesn&rsquo;t have to look like maintained open source code. It could look more like sharing the specifications. Some markdown files, some diagrams, a clear description of what the system does and how it&rsquo;s structured. Enough for someone else&rsquo;s assistant to pick it up and build their own version. Repeatable systems that people can share and build on without anyone having to maintain a repository of code.</p>
<p>I think of it a bit like home improvements. You can build a custom shelf for your garage, and it works great because you know the space, the weight it needs to hold, and how you&rsquo;re going to use it. Turning that into a product you sell at a hardware store is a completely different undertaking. But showing your neighbor the design so they can build their own version for their space? That&rsquo;s easy, and everyone benefits.</p>
<h2 id="the-pendulum">The Pendulum</h2>
<p>Now here&rsquo;s where the cybersecurity part of my brain kicks in.</p>
<p>Custom software, even internal and personal software, still carries risk. Every tool I&rsquo;ve built is code that runs on my systems. Code that processes data, makes network requests, and interacts with APIs. I trust it because I&rsquo;ve been involved in building it, reviewing it, and testing it. But that&rsquo;s me, and I do this for a living.</p>
<p>When you zoom out, the picture gets more interesting. More people building their own tools means a lot more code running on a lot more systems, with less formal review than we&rsquo;d typically see from an established software vendor. And when any of that software ends up on the public internet, or gets distributed as a downloadable application, the stakes go up fast. You&rsquo;re taking on responsibility for code running on other people&rsquo;s computers, with all the vulnerability, stability, and maintenance concerns that come with it. Update servers to run. Supply chains to think about. These aren&rsquo;t unsolvable problems. But they are problems, and they multiply quickly.</p>
<p>And it&rsquo;s not like the existing world of software was perfect, either. People have always shipped flawed code. Plenty of applications have gone unreviewed due to understaffing, tight deadlines, or just not knowing where the problems were. Security incidents aren&rsquo;t new. What seems new is the volume. There&rsquo;s an exponential increase in software being built and deployed, with less formal review than before. The people doing it aren&rsquo;t writing code in the traditional sense. They&rsquo;re building. There&rsquo;s code involved, but the relationship to it is different in many cases.</p>
<p><img alt="A glowing neon silhouette walking a thin luminous tightrope across the frame" loading="lazy" src="/img/posts/build-or-buy/tightrope.jpg"></p>
<p>A lot of that software will work fine. Some of it will be deployed on internal networks and serve its purpose without issue. Some won&rsquo;t. There will be incidents. There will be a correction. Best practices for responsibly building and maintaining <em>personal software</em> will emerge. Businesses may need one set of practices, individuals another, and insurance companies yet another.</p>
<p>And of course, we could be growing the most advanced form of technical debt we&rsquo;ve ever experienced. Both at the small, personal level, where tools I built last month already need attention, and at the large, interconnected level, where millions of custom systems are quietly depending on APIs, models, and services that could change or disappear at any time.</p>
<p>I&rsquo;m optimistic, though, that the security capabilities of our assistants and agents could grow alongside the building capabilities. The same tools that help build software can also help review it, audit it, and catch problems. They just need to be applied. If that keeps pace, and there&rsquo;s reason to think it could, the pendulum could find an equilibrium faster than it otherwise would.</p>
<h2 id="where-this-leaves-me">Where This Leaves Me</h2>
<p>I&rsquo;m going to keep building. The tools I&rsquo;ve made for myself are useful, and the process of building them has been one of the more rewarding parts of working with AI, for me. The unit of software is getting smaller. The audience for a piece of software might be one person. That changes what building, sharing, and maintaining software looks like, and we&rsquo;re still early in figuring out the norms for it.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Your AI Assistant Can Talk</title>
      <link>https://chriscantey.com/posts/2026-02-18-your-ai-assistant-can-talk/</link>
      <pubDate>Wed, 18 Feb 2026 00:00:00 +0000</pubDate>
      <guid>https://chriscantey.com/posts/2026-02-18-your-ai-assistant-can-talk/</guid>
      <description>Adding local voice notifications to PAI with Kokoro TTS. No cloud APIs, no GPU, no subscription. Your assistant speaks to you through your browser.</description>
      <content:encoded><![CDATA[<p>One of the neat features built into <a href="https://github.com/danielmiessler/PAI" target="_blank" rel="noopener noreferrer">PAI</a>
 is voice feedback. Your assistant can talk to you. It announces what phase it&rsquo;s in, tells you when something finishes, and lets you know when it needs your attention.</p>
<p>The way PAI ships this out of the box is through a built-in voice server that uses <a href="https://elevenlabs.io/" target="_blank" rel="noopener noreferrer">ElevenLabs</a>
 for text-to-speech. It sounds great. But it&rsquo;s designed for a setup where PAI is running locally on your Mac, and that&rsquo;s not how I run mine.</p>
<h2 id="how-pais-built-in-voice-works">How PAI&rsquo;s Built-In Voice Works</h2>
<p>PAI&rsquo;s voice server uses macOS <code>afplay</code> to play audio and <code>osascript</code> for desktop notifications. If you&rsquo;re sitting at the Mac where PAI is running, it works well. But if your assistant lives in a VM on another machine, like mine does, there&rsquo;s nobody sitting at that machine to hear it.</p>
<p>My whole setup is built around keeping my AI assistant in a Linux VM and connecting to it from whatever computer I happen to be on. I don&rsquo;t love opening ports on my daily drivers, so I wanted everything flowing in the pull direction. The assistant pushes nothing to my machines. My machines subscribe to what they want.</p>
<p>That meant I needed voice to work the same way: generated on the assistant&rsquo;s side, streamed to wherever I&rsquo;m listening.</p>
<h2 id="finding-the-right-voice">Finding the Right Voice</h2>
<p>My first approach was to modify the built-in voice server. I kept the same architecture but added a way to stream audio over WebSocket to a browser on another machine. For the actual speech generation, I started with ElevenLabs since that&rsquo;s what PAI uses natively.</p>
<p>The ElevenLabs voices are awesome and there are so many to choose from. I loved the way they sounded. But PAI is chatty. It announces every phase of the Algorithm, every task completion, every time it needs your input. And I wanted it to be chatty. I burned through eighty dollars in API credits in the first month, though, and that was a little more than I wanted to spend on hearing &ldquo;entering the observe phase&rdquo; five hundred times.</p>
<p>I wanted to let it talk as much as it wanted, so I went looking for something I could run locally.</p>
<h2 id="kokoro-tts">Kokoro TTS</h2>
<p><a href="https://github.com/hexgrad/kokoro" target="_blank" rel="noopener noreferrer">Kokoro</a>
 is an 82-million parameter open-source text-to-speech model. What I love about it:</p>
<ul>
<li><strong>It works on CPU.</strong> No GPU required. It runs anywhere Docker runs.</li>
<li><strong>It&rsquo;s fast.</strong> Generates a typical notification in 1 to 3 seconds on CPU.</li>
<li><strong>It&rsquo;s tiny.</strong> 82 million parameters. The model weights are about 330MB.</li>
<li><strong>Lots of voices.</strong> Dozens of options across multiple accents and languages.</li>
</ul>
<p>Kokoro has over 7.6 million monthly downloads on HuggingFace and is the top-ranked open-source model on the TTS Arena leaderboard. For a model you can run on a basic VM with no GPU, it punches way above its weight.</p>
<h2 id="how-it-works">How It Works</h2>
<p>The architecture is simple. Two Docker containers and a browser tab.</p>
<p><img alt="Voice architecture: PAI hooks send notifications to the voice server, which generates speech through Kokoro TTS and streams it over WebSocket to your browser." loading="lazy" src="/img/posts/voice-architecture-diagram.jpg"></p>
<ol>
<li>PAI&rsquo;s existing hooks fire a POST request to <code>/notify</code> with a message. This is the same API endpoint the built-in voice server uses, so nothing in PAI needs to change.</li>
<li>The voice server sends the text to a Kokoro sidecar container.</li>
<li>Kokoro generates speech and returns audio.</li>
<li>The voice server broadcasts the audio over WebSocket to every connected client.</li>
<li>Your browser (or any WebSocket client) plays it.</li>
</ol>
<p>The voice server itself is about 370 lines of TypeScript running on Bun. The Kokoro sidecar is about 180 lines of Python. Both run in Docker on the same network as the portal server from <a href="https://chriscantey.com/posts/2026-02-14-pai-companion/">PAI Companion</a>
.</p>
<h2 id="a-drop-in-replacement">A Drop-In Replacement</h2>
<p>I packaged it all up as an optional voice module for <a href="https://github.com/chriscantey/pai-companion" target="_blank" rel="noopener noreferrer">PAI Companion</a>
, the same repo I use to add a portal, file exchange, and design system to PAI. If you&rsquo;re not familiar with PAI Companion, I wrote about it in <a href="https://chriscantey.com/posts/2026-02-14-pai-companion/">an earlier post</a>
.</p>
<p>For getting it connected, I didn&rsquo;t want to fork PAI&rsquo;s hooks or rewrite any of the integration code. I wanted to leave PAI as is. So though I started from scratch, I wanted it to be a drop-in replacement for the built-in voice server:</p>
<ul>
<li>Same URL: <code>localhost:8888</code></li>
<li>Same API: <code>POST /notify</code> with <code>{ message, title, voice_enabled, voice_name }</code></li>
<li>All existing PAI hooks work without any modification</li>
</ul>
<p>The only difference is what happens behind that endpoint (within the assistant VM). Instead of calling ElevenLabs and playing audio through macOS speakers, it generates speech locally on the assistant&rsquo;s VM and streams it to wherever you&rsquo;re listening.</p>
<h2 id="what-you-hear">What You Hear</h2>
<p>Here&rsquo;s what it sounds like in practice. When your assistant starts a new phase of the Algorithm, you hear something like:</p>
<blockquote>
<p>&ldquo;Entering the observe phase.&rdquo;</p></blockquote>
<p>When a task completes:</p>
<blockquote>
<p>&ldquo;Portal report created at your-vm-ip port 8080.&rdquo;</p></blockquote>
<p>When something needs your attention:</p>
<blockquote>
<p>&ldquo;Waiting for your input on the deployment plan.&rdquo;</p></blockquote>
<p>This is all stuff PAI is already saying. It&rsquo;s functional. You leave a browser tab open, go make coffee, and your assistant tells you when it&rsquo;s done or when it needs you. That&rsquo;s the whole point. You can now hear it, even when PAI is running on a completely different machine.</p>
<h2 id="choosing-a-voice">Choosing a Voice</h2>
<p>Kokoro comes with dozens of voices. The voice module includes a preview page where you can listen to each one and pick the one you like. Right now I&rsquo;m using <code>af_heart</code>, but there are plenty of options across accents and languages and I hop around sometimes. You can even have your assistant pick a voice for you.</p>
<h2 id="listening">Listening</h2>
<p>The voice module gives you two ways to listen, depending on your setup:</p>
<p><strong>Standalone player.</strong> If you just want voice without the rest of PAI Companion, this is a simple HTML page you open in any browser. It connects to the voice server, shows connection status, and plays notifications as they come in. Dark theme, centered layout, volume control.</p>
<p><strong>Portal widget.</strong> If you&rsquo;re already running the PAI Companion portal, a small floating box sits in the bottom-right corner of every portal page. It runs in the background, so you get voice without opening another tab. Mute toggle included.</p>
<p>Both auto-reconnect if the connection drops, and both remember your volume setting.</p>
<h2 id="setting-it-up">Setting It Up</h2>
<p>If you already have PAI Companion set up, pull the latest:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#8be9fd;font-style:italic">cd</span> ~/pai-companion <span style="color:#ff79c6">&amp;&amp;</span> git pull
</span></span></code></pre></div><p>If you&rsquo;re starting fresh, clone the repo and set up the core companion first. There&rsquo;s a walkthrough in <a href="https://chriscantey.com/posts/2026-02-14-pai-companion/">the PAI Companion post</a>
.</p>
<p>Once you have the repo up to date, open Claude Code and tell your assistant:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>Read ~/pai-companion/voice/INSTALL.md and follow the setup phases.
</span></span></code></pre></div><p>Your assistant handles the rest. It will build the Kokoro base image (this downloads model weights from HuggingFace and may take about 10 minutes the first time), start the Docker containers, set up the web client, and configure upgrade protection so PAI updates don&rsquo;t overwrite your voice server.</p>
<p><strong>A note on resources:</strong> The build temporarily needs about 15GB of free disk space (it settles to around 5GB afterward). Plan for 30GB+ total on your VM, and at least 8GB of RAM. 16GB is more comfortable if you&rsquo;re running other things alongside your assistant.</p>
<p>Full details are in the <a href="https://github.com/chriscantey/pai-companion/blob/main/voice/README.md" target="_blank" rel="noopener noreferrer">README</a>
.</p>
<h2 id="whats-next">What&rsquo;s Next</h2>
<p>I also built a macOS menu bar client in Swift that connects over WebSocket and lives in the system tray. If anyone wants that code, I can add it to the repo as an optional extra. For the purposes of sharing, the browser-based approach covers most setups without requiring a native app.</p>
<p>I&rsquo;m not even sure this is the best architecture for this. If you&rsquo;ve found a different way to get voice out of a remote or VM-based assistant setup, I&rsquo;d love to hear about it. Reach out on LinkedIn or open an issue on the repo.</p>
<p>If you&rsquo;re running PAI, or especially PAI Companion, and want your system to talk to you, the <a href="https://github.com/chriscantey/pai-companion/tree/main/voice" target="_blank" rel="noopener noreferrer">voice module is ready to try</a>
.</p>
]]></content:encoded>
    </item>
    <item>
      <title>AI-Assisted 3D Printing: What Works and What Doesn&#39;t</title>
      <link>https://chriscantey.com/posts/2026-02-17-ai-assisted-3d-printing/</link>
      <pubDate>Tue, 17 Feb 2026 00:00:00 +0000</pubDate>
      <guid>https://chriscantey.com/posts/2026-02-17-ai-assisted-3d-printing/</guid>
      <description>I&amp;#39;ve been experimenting with using LLMs to help me build 3D printed objects. Here&amp;#39;s what I&amp;#39;ve learned about where it shines and where it falls short.</description>
      <content:encoded><![CDATA[<p>I took the plunge into the 3D printing hobby a few years back. I&rsquo;ve still got my first printer, a Bambu Lab A1, and I love it. Great machine. But I&rsquo;m not a CAD person. I know enough Blender to get by, and I&rsquo;ve built things I&rsquo;ve printed there, but it&rsquo;s not my favorite tool for making 3D printable objects. I&rsquo;ve done some work in Fusion 360 and FreeCAD too. I enjoy Fusion more, but regardless, none of these are tools I&rsquo;m deeply proficient in.</p>
<p>So it occurred to me to ask if an LLM could help with this too. I think I asked ChatGPT something like &ldquo;what kinds of 3D model files can you generate?&rdquo; and was actually kind of surprised by the answer. It listed out a bunch of different 3D formats it could produce. That kicked off a few months of experimenting.</p>
<p>As you probably already know, LLMs seem to do well with generating code, and OpenSCAD is essentially code. It&rsquo;s a scripting language for 3D geometry. Variables, modules, boolean operations, all expressed in text. So the same way an LLM can write you a solid SVG or a well-structured HTML page, it can write OpenSCAD that produces real, printable geometry.</p>
<p>Of course there are diffusion-based approaches to 3D generation now, like how AI image generators work, but that&rsquo;s not what&rsquo;s happening here. This is actually constructing the object from code, the same way you&rsquo;d build an app or a website.</p>
<p>STL files are essentially raw triangle meshes with no parameters or structure, just coordinates. LLMs seem to be able to produce those too, but the results were less precise and much harder to iterate on, at least for me so far. The OpenSCAD approach seemed to be more consistent overall.</p>
<p><img alt="Code flowing into 3D shapes" loading="lazy" src="/img/posts/ai-3d-printing/article-workflow.jpg"></p>
<p>Like most of these mental unlocks that come with Claude Code and similar tools, my brain was just going wild with ideas the moment it clicked.</p>
<p>But I&rsquo;ve since learned that I have to keep myself grounded, because for every project where it helped me get from idea to printed object in an hour or an afternoon, there&rsquo;s one where I spent way too much time going back and forth through 20-plus revisions before I realized I was spinning my wheels. I probably could have just modeled it myself in Blender or made myself learn Fusion better.</p>
<p>So I want to share where I&rsquo;m at with it, what&rsquo;s worked for me, and what hasn&rsquo;t.</p>
<h2 id="the-projects-that-worked">The Projects That Worked</h2>
<h3 id="bulb-diffuser">Bulb Diffuser</h3>
<p>This was my cleanest and fastest success. I had an LED bulb in a lamp and wanted a clip-on diffuser to spread the light more evenly into the lampshade. I was imagining a ring with grippy fingers that could clip onto the bulb, with a wide outer section thin enough to be translucent.</p>
<div class="stl-viewer-wrap">
  <div class="stl-container" id="stl-bulb-diffuser-stl" style="height: 380px;" data-stl="/stl/bulb-diffuser.stl" data-color="0xF39C12" data-rotation="x:-90"></div>
  <p class="stl-caption">The bulb diffuser. A wide disc with clip fingers that grip the LED bulb.</p>
  <p class="stl-help">Drag to rotate &middot; Scroll to zoom &middot; Right-click to pan</p>
</div>

<p>I built this one through my Claude Code + PAI setup. The AI wrote the OpenSCAD, and because it&rsquo;s parametric by nature, all the key dimensions lived as variables in the file.</p>
<p>Working with OpenSCAD like this probably comes as no surprise to people who are already familiar with it, but this was my first time touching it. So that was a whole revelation on top of working with the AI tools to do it.</p>
<p>The AI handled the geometry well because it was relatively straightforward. The trickier part was figuring out the right thickness for light diffusion. My PLA became translucent at about 0.4mm, just two layers at standard layer height. That&rsquo;s maybe a physics insight more than a geometry one. But once we had it, the parametric approach meant I could tweak the thickness and re-render quickly.</p>
<p>I only had to do about two print iterations, and that was mainly just dialing in the thickness. The final print clips onto the bulb and works exactly as intended.</p>
<p><strong>Why it worked:</strong> Simple geometry that was easy to describe in words. Clear functional requirements (clip on, diffuse light). Easy to verify (does it fit? does light come through?). The code-based approach made iteration fast.</p>
<h3 id="film-developer-bottle-hooks">Film Developer Bottle Hooks</h3>
<p>I develop color film at home and have a pretty basic DIY setup. I use an immersion circulator (the kind you&rsquo;d normally use for sous vide cooking) to heat water in a dish tub. The developer bottles sit in the warm water to stay at temp, but they tend to drift around and could easily tip over.</p>
<p>I wanted a hook that clips over the tub edge and cradles a bottle to keep it in place. It wasn&rsquo;t something I strictly needed to fix, but it was one of those things where if I could get a quick solution without spending a lot of time on it, that&rsquo;d be great.</p>
<div class="stl-viewer-wrap">
  <div class="stl-container" id="stl-bottle-hook-stl" style="height: 380px;" data-stl="/stl/bottle-hook.stl" data-color="0xc471ed" data-rotation="x:-90"></div>
  <p class="stl-caption">The bottle hook. Clips over the tub edge with a cradle for the bottle.</p>
  <p class="stl-help">Drag to rotate &middot; Scroll to zoom &middot; Right-click to pan</p>
</div>

<p>This one I did through ChatGPT, before I had my current Claude Code setup. It generated the STL files directly through conversation. The process was iterative. First version, test fit, adjust dimensions, new version. I gave it the exact measurements (tub lip: 15.6mm, bottle diameter: 102mm) and described the mechanical concept I wanted. A clip with some pressing tension over the tub lip, and a half-cup cradle inside the tub for the bottle.</p>
<p>You can tell by looking at it that the result isn&rsquo;t the prettiest piece of geometry. The shape is a little odd. But it only took one test print before we had something that worked, and I didn&rsquo;t need it to look nice. I just needed something quick and functional. It&rsquo;s the exact measurements of my bottles and the side of my inexpensive dish tub. A good scenario for this kind of AI-assisted design: getting from nothing to something useful quickly when precise fit matters more than aesthetics.</p>
<p><strong>Why it worked:</strong> The shape was fairly easy to describe with measurements and mechanical behavior. Exact dimensions drove the design. The feedback loop was fast.</p>
<h3 id="film-scanner-leveling-plate">Film Scanner Leveling Plate</h3>
<p>I wanted a way to level my film scanner easily without buying some fancy device from a photography store if I could help it. This ended up being a bigger project than the bottle hooks, with more iterations, but the exploration was worthwhile. It was fun, and it taught me a lot of terms and concepts about designing parts that I didn&rsquo;t know before.</p>
<p>The base design was a flat rectangle with rounded corners, a hex grid pattern for rigidity without excess weight, and mounting bosses. But I wanted a little bit more.</p>
<p>I wanted embeddable screw holes for adjustable feet. A three-point leveling system, which the AI actually helped me figure out was more efficient than four-point for this application. And I needed it to mate correctly with my existing film scanner (a 3D printed scanner kit from <a href="https://tonephotographic.com/" target="_blank" rel="noopener noreferrer">Tone</a>
 that I&rsquo;d already assembled) and a specific LED light panel, holding both in place.</p>
<div class="stl-grid">
<div class="stl-viewer-wrap">
  <div class="stl-container" id="stl-leveling-plate-stl" style="height: 350px;" data-stl="/stl/leveling-plate.stl" data-color="0x2dd4bf"></div>
  <p class="stl-caption">Main plate with hex grid and mounting bosses</p>
  <p class="stl-help">Drag to rotate &middot; Scroll to zoom &middot; Right-click to pan</p>
</div>

<div class="stl-viewer-wrap">
  <div class="stl-container" id="stl-leveling-foot-stl" style="height: 350px;" data-stl="/stl/leveling-foot.stl" data-color="0xc471ed"></div>
  <p class="stl-caption">Adjustable leveling foot (screws into plate)</p>
  <p class="stl-help">Drag to rotate &middot; Scroll to zoom &middot; Right-click to pan</p>
</div>

</div>
<p>This was another ChatGPT project, and it took a fair number of iterations to get the screw placement right, the fit with the existing scanner body, and the overall dimensions dialed in. The AI seemed to do well with this because the core geometry was still fundamentally flat 3D planes that we were just extruding. A flat plate with holes and bosses. And it helped me think through the leveling approach, which I wouldn&rsquo;t have known to research on my own.</p>
<p><img alt="2D cross-sections of the leveling plate showing both faces" loading="lazy" src="/img/posts/ai-3d-printing/leveling-plate-2d.png"></p>
<p><strong>Why it worked:</strong> Essentially a 2D problem extruded into 3D. Precise measurements drove the design. The layout and the patterns were pretty straightforward.</p>
<h2 id="where-it-struggled">Where It Struggled</h2>
<h3 id="terraforming-mars-tile-grid">Terraforming Mars Tile Grid</h3>
<p>I play a lot of Terraforming Mars (tabletop game), and I&rsquo;d had some initial luck getting AI to make me custom stuff for the game really quickly.</p>
<p>A little Mars globe on a pedestal to use as the first player marker. That came together fast and looked great.</p>
<p><img alt="The Mars first player marker. A globe on a pedestal." loading="lazy" src="/img/posts/ai-3d-printing/mars-marker-render.png"></p>
<p>So I got excited and decided to go a little bigger. I figured it would be pretty simple. I just wanted a frame to hold all 60 hex tiles on the game board. The board has a specific hex layout and I just had to tile it and get the dimensions right.</p>
<div class="stl-viewer-wrap">
  <div class="stl-container" id="stl-mars-grid-full-stl" style="height: 400px;" data-stl="/stl/mars-grid-full.stl" data-color="0x12c2e9" data-rotation="x:-90"></div>
  <p class="stl-caption">The full 60-hex grid layout. The grid geometry itself works well.</p>
  <p class="stl-help">Drag to rotate &middot; Scroll to zoom &middot; Right-click to pan</p>
</div>

<p>That part did take some iteration, but I was enjoying the process. I got to bust out the calipers and check exact dimensions. We did a bunch of single-hex test prints to dial in the various insets and tolerances, and we arrived at one that worked really well. If you zoom in on the viewer above, you can probably see where the tiles sit.</p>
<p>But this hex grid is way too big to fit on my 3D printer in one piece. So we had to come up with a way to split it into four parts and join them back together. That&rsquo;s where everything fell apart and I started wasting a lot of time and prints.</p>
<p>We tried dovetails. The shapes came out wrong. We tried magnet pockets. The geometry constraints (2mm base thickness, narrow solid ring between the tile pockets and the see-through openings) made it really difficult. The LLM would generate code that looked reasonable, but the physical results didn&rsquo;t work, seemingly because it couldn&rsquo;t &ldquo;see&rdquo; how the pieces actually fit together in 3D space.</p>
<p>Another problem seemed to be that I was asking it to make really tiny changes across a really small space, and I just didn&rsquo;t have good words for what I actually needed. We weren&rsquo;t connecting on the spatial relationships I was trying to describe. After 13 versions and multiple joining approaches, we have a grid that holds tiles perfectly but we&rsquo;re still figuring out how the pieces connect.</p>
<p>I think I probably could have gotten there with more time. But the simplicity of the object also means I could probably just take what the AI has already built for me and do the simple joining modifications myself in Fusion or Blender. That&rsquo;s actually probably what I&rsquo;ll do next. It&rsquo;s just taken a backburner because it turned out not to be a ten-minute LLM build.</p>
<p><strong>Why it struggled:</strong> The joining problem required understanding how parts fit together in 3D space while dealing with tolerances, material constraints, and assembly angles all at once. I couldn&rsquo;t explain the geometry well enough in words. Each joining method attempt required understanding clearances and physical constraints that text descriptions just don&rsquo;t convey well.</p>
<p><img alt="The gap between intention and execution" loading="lazy" src="/img/posts/ai-3d-printing/article-limits.jpg"></p>
<h3 id="the-pattern">The Pattern</h3>
<p>Looking across all these projects, a pattern emerged:</p>
<p><strong>AI seems to work well when:</strong></p>
<ul>
<li>The geometry can be fully described with measurements and simple shapes</li>
<li>The design is essentially &ldquo;2D plus extrusion&rdquo; or built from primitive solids</li>
<li>The functional requirements are clear and testable (does it fit? does it clip?)</li>
<li>You&rsquo;re building something new from scratch rather than modifying existing geometry</li>
<li>You can work through it in code (OpenSCAD) rather than raw mesh data</li>
</ul>
<p><strong>AI seems to struggle when:</strong></p>
<ul>
<li>The design requires understanding how multiple parts physically interact</li>
<li>Geometry is constrained in multiple dimensions simultaneously</li>
<li>You can&rsquo;t find the right words to describe what you need spatially</li>
<li>You&rsquo;re iterating on complex shapes rather than dimensions</li>
</ul>
<h2 id="the-workflow-that-emerged">The Workflow That Emerged</h2>
<p>Here&rsquo;s what I&rsquo;ve settled on after a few months, and it&rsquo;s the piece I&rsquo;d actually recommend to other people.</p>
<p><strong>Start with a 2D description.</strong> Before anything else, describe an overhead or side view. I&rsquo;m not talking about actually drawing anything (I&rsquo;m terrible at drawing). I mean describe it in the form of a 2D sketch and work with the AI on that. Get the dimensions and relationships nailed down in 2D before going to 3D. This forces you to think about how the parts relate to each other, and it gives the AI something concrete to work from.</p>
<p><strong>Use OpenSCAD, not direct STL generation.</strong> This was the biggest lesson for me. Having the AI write OpenSCAD code instead of generating raw mesh data made a huge difference for me. The code is readable. It&rsquo;s parametric. All the dimensions live as variables in the file. You can tweak and re-render without re-explaining the whole design.</p>
<p><strong>Test prints along the way.</strong> This isn&rsquo;t specific to AI-assisted design. It&rsquo;s just good practice if you&rsquo;re building anything for 3D printing. Print a small section first. A 4-hex test piece instead of the full 60-hex grid. A smaller version of the diffuser to test multiple thicknesses. This catches fit issues before you&rsquo;ve spent hours printing the wrong thing.</p>
<p><img alt="Grid of screens showing different angles of a 3D object" loading="lazy" src="/img/posts/ai-3d-printing/article-gallery.jpg"></p>
<p><strong>Version your files, or ask it to version them for you.</strong> It helps to not overwrite your working designs. Let the AI know that you want to keep all of its versions so you can refer back to things. I was working in OpenSCAD source files for the most part, and then had it export STLs when I was ready to take something to the printer. But regardless of what format you&rsquo;re working in, keep versions.</p>
<p><strong>Have it build you something visual to iterate with.</strong> This was easier for me than a folder full of files or trying to talk about designs purely in text. I had the AI build me a viewer page early on where I could see renders from different angles, spin models around, and compare versions side by side.</p>
<h2 id="the-skill-and-the-gallery">The Skill and the Gallery</h2>
<p>If you&rsquo;ve seen some of my other projects, it should come as no surprise that I have it do this for me too. It&rsquo;s a pattern I use a lot, and I love this part of the workflow.</p>
<p>Early on in the process, I asked the AI to build me a gallery-style view for each print project. Once I moved to the Claude Code + PAI workflow, I codified this into something more consistent. It&rsquo;s a skill in PAI, basically a set of instructions that tells the AI how to generate these pages for each project.</p>
<p>For every version we work through, I get multi-angle renders (isometric, side, top views), an interactive STL viewer I can spin around in my browser or on my phone, and a version history showing how the design evolved. All of it served through my <a href="/posts/2026-02-14-pai-companion/">portal setup</a>
, so I can pull it up on any device without opening a modeling program or SSHing into anything.</p>
<p><img alt="Screen recording scrolling through the 3D print portal pages" loading="lazy" src="/img/posts/ai-3d-printing/gallery-demo.gif"></p>
<p>I&rsquo;m very visual, and generating web views of things has turned out to be one of the most useful patterns in this whole setup. I didn&rsquo;t even know that Three.js could render STL files in a browser until I asked the AI about it and it helped me figure out how. The ability to see the model from multiple angles, compare it to the previous version, and then describe what to change next, all from a browser tab, makes the iteration loop feel really smooth.</p>
<p>The skill itself is what makes this consistent across projects. It&rsquo;s a markdown file that gives the AI context about my printer specs, OpenSCAD patterns, design principles, and the gallery page structure. Any time I start a new print project, it already knows the workflow and where to put my renders and previews.</p>
<h2 id="is-it-easier-than-learning-cad">Is It Easier Than Learning CAD?</h2>
<p>Sometimes. Probably not in general.</p>
<p>For the bulb diffuser and the bottle hooks, using the AI workflow was significantly faster for me than opening Fusion 360 would have been. That&rsquo;s partly because I just haven&rsquo;t spent the time with that program yet and may never get around to it. It&rsquo;s not my world. The designs were simple enough that describing them in words was the fastest path from idea to object.</p>
<p>For the tile grid, I probably would have been better off doing the joining geometry myself in Fusion or Blender. The joining problem involved so many interacting physical constraints (clearances, material thickness, assembly angles) that going back and forth in text was just a clumsy way to approach it.</p>
<p>The sweet spot is functional parts with clear dimensions. Brackets, holders, clips, plates, enclosures. Things where I can say &ldquo;I need a rectangle that&rsquo;s 200mm by 135mm by 5mm with rounded corners and mounting holes here, here, and here&rdquo; and get a working result. These are also the kinds of things that don&rsquo;t need to look pretty, which helps.</p>
<p>If you already know CAD well, AI probably isn&rsquo;t replacing your workflow. But if you&rsquo;re like me and you&rsquo;re competent enough but not fast in traditional tools, AI can get you from concept to printed object in an afternoon for the right kinds of projects. Just go in knowing it has limits, and be ready to iterate.</p>
<h2 id="if-you-want-to-try-this">If You Want to Try This</h2>
<p>The core of my approach is a set of instructions (a &ldquo;skill&rdquo; in Claude Code or PAI terms) that I give my AI assistant. It provides context about 3D printing: my printer specs, OpenSCAD patterns, design principles, and the lessons learned from projects like these.</p>
<p>Head on over to the repo for a draft of <a href="https://github.com/chriscantey/skill-3d-printing" target="_blank" rel="noopener noreferrer">my 3D printing skill.</a>
</p>
<p>If you&rsquo;re using PAI (<a href="/posts/2026-02-14-pai-companion/">here&rsquo;s my setup</a>
), the quick install is:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#8be9fd;font-style:italic">cd</span> ~ <span style="color:#ff79c6">&amp;&amp;</span> git clone https://github.com/chriscantey/skill-3d-printing.git
</span></span></code></pre></div><p>Then tell your assistant:</p>
<pre tabindex="0"><code>Read ~/skill-3d-printing/INSTALL.md and follow its instructions.
</code></pre><p>It&rsquo;ll walk you through setup, including asking about your printer specs. Manual install instructions are in the repo if you&rsquo;d rather do it yourself.</p>
<p>I don&rsquo;t think this skill is complete or even particularly well polished. It&rsquo;s the result of a few months of trial and error, and it reflects what&rsquo;s worked for me with the projects I&rsquo;ve taken on so far. I would love it if someone who knows more about OpenSCAD, 3D modeling, or mechanical engineering could take this, improve on it, and share what they learn. It may be helpful to others who want to dive in and start playing around with this like I did, in a non-professional, just-for-fun sense.</p>
<p>Big picture, even without this skill, the workflow section above is the important part. Start with 2D descriptions. Use something like OpenSCAD. Print test pieces. Have it render you an interactive viewer or something to track your work. Keep your expectations calibrated. And remember that &ldquo;just a language model&rdquo; can mean a whole lot when the output format is code.</p>
]]></content:encoded>
    </item>
    <item>
      <title>PAI Companion: A Visual Jumpstart for Your AI Assistant</title>
      <link>https://chriscantey.com/posts/2026-02-14-pai-companion/</link>
      <pubDate>Sat, 14 Feb 2026 00:00:00 +0000</pubDate>
      <guid>https://chriscantey.com/posts/2026-02-14-pai-companion/</guid>
      <description>A simple add-on that gives your PAI installation a portal, file exchange, and visual output system. Work in progress, local VMs only.</description>
      <content:encoded><![CDATA[<p>If you&rsquo;ve been following along with this series, you&rsquo;ve got an AI assistant running in a VM. Maybe you&rsquo;ve built the <a href="/posts/2026-02-11-get-files-into-your-vm/">file drop tool</a>
 and started exploring what it can do. At some point you&rsquo;ve probably asked your assistant to build you a web page or a dashboard, and it worked, but then you had to figure out how to keep it running. Where does it serve the page? What port? And when you close the session, the server disappears and you&rsquo;re setting it up again next time.</p>
<p>That&rsquo;s the gap PAI Companion fills. It gives your assistant a single, persistent service that serves all the web content it creates for you. One Docker container, always running, no re-explaining the setup every session.</p>
<h2 id="what-it-is">What It Is</h2>
<p><a href="https://github.com/chriscantey/pai-companion" target="_blank" rel="noopener noreferrer">PAI Companion</a>
 is a simple add-on for <a href="https://github.com/danielmiessler/PAI" target="_blank" rel="noopener noreferrer">PAI</a>
, Daniel Miessler&rsquo;s open-source framework for enhancing Claude Code. It adds some infrastructure for visual output so your assistant can create web pages, dashboards, reports, and styled documents that you can view in your browser. It does make some additions to your PAI configuration (steering rules, a design system, identity context), but it shouldn&rsquo;t break anything.</p>
<p>Here&rsquo;s what it sets up:</p>
<ul>
<li><strong>A portal server</strong> that serves web content your assistant creates. Ask it to build you something, and it shows up at a URL you can open from your host machine. One service, always running.</li>
<li><strong>A file exchange</strong> with drag-and-drop in the browser. Similar to the file drop tool from the last post, but integrated into the portal.</li>
<li><strong>A clipboard page</strong> for when your assistant generates text you want to copy, like an email draft or a code snippet.</li>
<li><strong>A dark theme design system</strong> so everything your assistant builds looks consistent and clean out of the box.</li>
<li><strong>Directory conventions</strong> that organize your home directory so files land in predictable places.</li>
<li><strong>A browsable skills catalog and agent roster</strong> so you can explore what your assistant can do from a web page. Click any skill to read its full definition, or any agent to see its profile and capabilities.</li>
<li><strong>A welcome page</strong> with example prompts and a quick explanation of how everything fits together.</li>
</ul>
<p><img alt="The skills catalog lets you browse every skill your assistant has and read its full definition." loading="lazy" src="/img/posts/pai-companion-skills.jpg"></p>
<p><img alt="The system overview shows your installation at a glance." loading="lazy" src="/img/posts/pai-companion-system.jpg"></p>
<p>This is just one approach to giving your assistant visual output. It&rsquo;s not the only way, and it&rsquo;s not necessarily a complete setup. It&rsquo;s a starting point that works for me and might work for you.</p>
<h2 id="who-this-is-for">Who This Is For</h2>
<p>This is probably most useful if you&rsquo;re someone who benefits from visual feedback. If you&rsquo;re comfortable reading terminal output all day, you might not need this. But if you like seeing things rendered in a browser, if dashboards and styled pages make information click faster for you, this gives your assistant the ability to communicate that way.</p>
<p>It&rsquo;s also helpful if you&rsquo;re running in a VM like I recommend. The portal gives you a clean way to view your assistant&rsquo;s output from your host machine without thinking about ports and file paths every time.</p>
<h2 id="who-this-is-not-for">Who This Is Not For</h2>
<p>If you&rsquo;re running PAI on a VPS or any server exposed to the internet, this is not for you. The portal server runs over HTTP. There&rsquo;s no authentication, no encryption, and no access controls. Anyone who can reach the port can see whatever&rsquo;s being served.</p>
<p>This is designed for a VM on your local machine or your local network. That includes VMs running on your laptop, on a home server, or on a hypervisor like Proxmox. The point is it&rsquo;s on a network you control. That&rsquo;s a very different risk profile than something sitting on the open internet.</p>
<h2 id="what-to-expect">What to Expect</h2>
<p>I want to be straightforward: it&rsquo;s a work in progress. It should work. I&rsquo;ve helped a few friends set it up, and the package is based at least partially on the system I&rsquo;m actually running. But it&rsquo;s still evolving. Things might change. There might be rough edges.</p>
<p>The setup is designed to be resumable. Each phase is independently verifiable, so if something breaks or you need to come back to it, you can pick up where you left off.</p>
<h2 id="before-you-start">Before You Start</h2>
<p>You need a handful of things installed before running the companion setup. If you followed the <a href="/posts/2026-02-02-setting-up-your-personal-ai-assistant/">earlier setup post</a>
, you already have most of them. The only new addition is Docker.</p>
<p>If you haven&rsquo;t done the setup post yet, you&rsquo;ll need to install the basics first. Run everything as a regular user with sudo access, not as root. (If your distro didn&rsquo;t create one during installation, <a href="https://www.digitalocean.com/community/tutorials/how-to-create-a-new-sudo-enabled-user-on-ubuntu" target="_blank" rel="noopener noreferrer">here&rsquo;s how to set that up</a>
.)</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo apt update <span style="color:#ff79c6">&amp;&amp;</span> sudo apt install -y curl git zip
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>curl -fsSL https://bun.sh/install | bash <span style="color:#ff79c6">&amp;&amp;</span> <span style="color:#8be9fd;font-style:italic">source</span> ~/.bashrc
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>curl -fsSL https://claude.ai/install.sh | bash
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>git clone https://github.com/danielmiessler/PAI.git
</span></span><span style="display:flex;"><span>cp -r PAI/Releases/<span style="color:#ff79c6">$(</span>ls PAI/Releases/ | sort -V | tail -1<span style="color:#ff79c6">)</span>/.claude ~/ <span style="color:#ff79c6">&amp;&amp;</span> <span style="color:#8be9fd;font-style:italic">cd</span> ~/.claude <span style="color:#ff79c6">&amp;&amp;</span> sed -i <span style="color:#f1fa8c">&#39;s/--mode gui/--mode cli/&#39;</span> install.sh <span style="color:#ff79c6">&amp;&amp;</span> bash install.sh
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">[</span> -f ~/.zshrc <span style="color:#ff79c6">]</span> <span style="color:#ff79c6">&amp;&amp;</span> cat ~/.zshrc &gt;&gt; ~/.bashrc
</span></span><span style="display:flex;"><span>sed -i <span style="color:#f1fa8c">&#39;s|skills/PAI/Tools/pai.ts|PAI/Tools/pai.ts|g&#39;</span> ~/.bashrc
</span></span><span style="display:flex;"><span><span style="color:#8be9fd;font-style:italic">source</span> ~/.bashrc
</span></span></code></pre></div><p>Docker is the one thing the companion setup can&rsquo;t work without. If you don&rsquo;t have it yet:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>curl -fsSL https://get.docker.com | bash
</span></span><span style="display:flex;"><span>sudo usermod -aG docker <span style="color:#8be9fd;font-style:italic">$USER</span>
</span></span></code></pre></div><p>Log out and back in after that, then verify it works without sudo:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker run --rm hello-world
</span></span></code></pre></div><blockquote>
<p><strong>Why not let the assistant handle this?</strong> We don&rsquo;t give Claude Code sudo access. That&rsquo;s intentional. These prerequisites need elevated privileges, so you run them yourself. Once the companion is set up, nothing else needs sudo.</p></blockquote>
<p>The companion repo also has a <a href="https://github.com/chriscantey/pai-companion/blob/main/companion/PREREQUISITES.md" target="_blank" rel="noopener noreferrer">full prerequisites file</a>
 with optional extras like Playwright and useful CLI tools.</p>
<h2 id="installing-the-companion">Installing the Companion</h2>
<p>Once Docker is working and you&rsquo;ve got PAI v4.0 running, clone the repo into your VM:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git clone https://github.com/chriscantey/pai-companion.git ~/pai-companion
</span></span></code></pre></div><p>Then open PAI / Claude Code and say:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>Read ~/pai-companion/companion/INSTALL.md and follow the setup phases.
</span></span></code></pre></div><p>Your assistant handles the rest. It will walk through each phase, setting up the portal server, file exchange, clipboard, design system, and directory structure. When it&rsquo;s done, you&rsquo;ll have URLs for the portal, the file exchange, and the clipboard.</p>
<p>The first thing I&rsquo;d check out is the welcome page. It has example prompts you can try, a quick breakdown of how the system works, and links to the skills catalog and agent roster so you can browse what your assistant can do.</p>
<p><img alt="The welcome page gives you example prompts and a tour of the system." loading="lazy" src="/img/posts/pai-companion-welcome.jpg"></p>
<h2 id="whats-next">What&rsquo;s Next</h2>
<p>This is still being shaped. I&rsquo;ll probably do another pass on the package as I keep refining my own setup, and I&rsquo;d like to get more feedback from people actually using it. If you try it out and run into something, the <a href="https://github.com/chriscantey/pai-companion" target="_blank" rel="noopener noreferrer">GitHub repo</a>
 is the place to raise it.</p>
<hr>
<p><em>Part of the <a href="/tags/pai-setup/">PAI Setup Series.</a>
 Previous: <a href="/posts/2026-02-11-get-files-into-your-vm/">File Drops for Your AI Assistant VM</a>
</em></p>
]]></content:encoded>
    </item>
    <item>
      <title>File Drops for Your AI Assistant VM</title>
      <link>https://chriscantey.com/posts/2026-02-11-get-files-into-your-vm/</link>
      <pubDate>Wed, 11 Feb 2026 00:00:00 +0000</pubDate>
      <guid>https://chriscantey.com/posts/2026-02-11-get-files-into-your-vm/</guid>
      <description>Let&amp;#39;s build a drag-and-drop file upload so your AI assistant can work with your files.</description>
      <content:encoded><![CDATA[<!-- VIDEO LINK -->
<div style="background: rgba(196, 113, 237, 0.1); border-left: 3px solid #c471ed; padding: 1rem; border-radius: 0 6px 6px 0; margin: 1.5rem 0;">
  <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="currentColor" style="vertical-align: -0.25em; margin-right: 8px;"><path d="M19.615 3.184c-3.604-.246-11.631-.245-15.23 0-3.897.266-4.356 2.62-4.385 8.816.029 6.185.484 8.549 4.385 8.816 3.6.245 11.626.246 15.23 0 3.897-.266 4.356-2.62 4.385-8.816-.029-6.185-.484-8.549-4.385-8.816zm-10.615 12.816v-8l8 3.993-8 4.007z"/></svg><strong>Prefer video?</strong> <a href="https://youtu.be/VFJ0lCbmy-M" target="_blank" rel="noopener noreferrer">Watch this on YouTube</a>
</div>
<p>You followed the <a href="/posts/2026-02-02-setting-up-your-personal-ai-assistant/">setup guide</a>
, you&rsquo;ve got your AI assistant running in a VM, and now you&rsquo;re wondering: how do I actually get files in there?</p>
<p>If you&rsquo;re comfortable with the command line, scp or rsync work fine. If your virtualization software has built-in file sharing, that works too (though depending on how much you want to sandbox things, it may come with tradeoffs). But if you want something simple that works from any browser, we can build a drag-and-drop file upload in about five minutes.</p>
<p>If you followed along with the weather page at the end of the setup guide, this is another example of the same pattern, just slightly more advanced. You give your assistant a prompt, watch it work through the problem, and end up with a running tool. The more you do this, the more you start thinking of things you can build the same way.</p>
<h2 id="the-prompt">The Prompt</h2>
<p>Open a terminal in your VM, start Claude Code, and give it this:</p>
<blockquote>
<p>Build me a simple file upload server. I want to:</p>
<ul>
<li>Have a nice drag-and-drop web interface that I access from my browser</li>
<li>Save uploaded files to ~/uploads/</li>
<li>Limit file size to 100MB</li>
<li>Show upload progress
Use Bun. Keep it simple.</li>
</ul></blockquote>
<p>Your assistant will think through the request, plan its approach, write the code, and start the server. It will figure out the VM&rsquo;s IP address (since you&rsquo;re accessing it from another machine, not localhost) and give you a URL to open in your browser.</p>
<p>Drag a file in. Check <code>~/uploads/</code>. That&rsquo;s it.</p>
<h2 id="what-can-you-do-with-it">What Can You Do With It?</h2>
<p>This is where it gets interesting. The upload server itself is just plumbing. The real value is what happens once your assistant has access to those files.</p>
<p>Say you had a handful of meeting transcripts. You could drop them in, then ask your assistant to pull out all the action items, decisions, and blockers across every meeting.</p>
<blockquote>
<p>Analyze all meeting notes in ~/uploads/. Create:</p>
<ol>
<li>A consolidated action item list with owners and status</li>
<li>All decisions made and when</li>
<li>Current blockers and their resolution status</li>
<li>A timeline of how the project evolved</li>
</ol></blockquote>
<p>Or ask it to build you a nice dashboard view of that information, something you can open in your browser and actually scan through quickly.</p>
<p>The same idea applies to anything you might want to process: PDFs, notes, data exports, research. Once the files are accessible to your assistant, you can work with them conversationally. Describe what you want, and it builds the thing.</p>
<h2 id="making-it-permanent">Making It Permanent</h2>
<p>There&rsquo;s one problem with what we just built: the upload server only runs inside your current session. Close the terminal, and it&rsquo;s gone.</p>
<p>So ask your assistant to fix that. Something like:</p>
<blockquote>
<p>Can you set up the upload service to run long-term in the background? Pick a port where it can stay running, set it up as a service so it auto-restarts if it crashes or if the server reboots, and document how it&rsquo;s set up so we can refer back to it.</p></blockquote>
<p>Depending on what operating system you&rsquo;re running, your assistant will probably set up something like a systemd service (the standard way Linux manages background processes), choose a port, and make sure the upload server starts automatically. When it&rsquo;s done, your file drop should always be available, whether you&rsquo;re in a Claude Code session or not.</p>
<h2 id="before-you-leave-this-running">Before You Leave This Running</h2>
<p>A couple things worth thinking about.</p>
<h3 id="data-sensitivity">Data sensitivity</h3>
<p>Your VM sandbox keeps the assistant from accessing your main computer, but anything you drop into that uploads folder becomes part of what it can read and process. If the content is sensitive, consider whether you&rsquo;re comfortable with it being sent to the cloud for processing. Using example data while you&rsquo;re learning is a good approach. Get comfortable with how the system works, then decide what real data you&rsquo;re ready to bring in.</p>
<h3 id="network-exposure">Network exposure</h3>
<p>If you&rsquo;re running this in a VM on your local machine, the risk is relatively low. The upload form is only reachable from your network. But if you&rsquo;re running this on a VPS or any server exposed to the internet, this is not code you want sitting on an open port. There&rsquo;s no authentication, no encryption, and we haven&rsquo;t done any security review of what the assistant built. Anyone who can reach that port can upload files to your server. Keep this on a private network, or behind a firewall. If you need remote file access on a public server, that&rsquo;s a different problem that deserves a more thoughtful solution.</p>
<h2 id="whats-next">What&rsquo;s Next</h2>
<p>This is one small example of a bigger pattern. Your assistant can build tools, run them, and turn them into permanent services, all from a conversation. The upload server just happens to be a practical first step because it solves the &ldquo;how do I get files in here&rdquo; problem. From here, you can start exploring what else your assistant can do with the files you give it, and what other tools it can build for you along the way.</p>
<hr>
<p><em>Part of the <a href="/tags/pai-setup/">PAI Setup Series.</a>
 Previous: <a href="/posts/2026-02-02-setting-up-your-personal-ai-assistant/">Setting Up Your Personal AI Assistant</a>
</em></p>
]]></content:encoded>
    </item>
    <item>
      <title>Setting Up Your Personal AI Assistant</title>
      <link>https://chriscantey.com/posts/2026-02-02-setting-up-your-personal-ai-assistant/</link>
      <pubDate>Mon, 02 Feb 2026 00:00:00 +0000</pubDate>
      <guid>https://chriscantey.com/posts/2026-02-02-setting-up-your-personal-ai-assistant/</guid>
      <description>A practical guide to setting up Claude Code with PAI on a Linux VM.</description>
      <content:encoded><![CDATA[<!-- VIDEO LINK -->
<div style="background: rgba(196, 113, 237, 0.1); border-left: 3px solid #c471ed; padding: 1rem; border-radius: 0 6px 6px 0; margin: 1.5rem 0;">
  <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="currentColor" style="vertical-align: -0.25em; margin-right: 8px;"><path d="M19.615 3.184c-3.604-.246-11.631-.245-15.23 0-3.897.266-4.356 2.62-4.385 8.816.029 6.185.484 8.549 4.385 8.816 3.6.245 11.626.246 15.23 0 3.897-.266 4.356-2.62 4.385-8.816-.029-6.185-.484-8.549-4.385-8.816zm-10.615 12.816v-8l8 3.993-8 4.007z"/></svg><strong>Prefer video?</strong> <a href="https://www.youtube.com/watch?v=ZZ6B06GfD-w" target="_blank" rel="noopener noreferrer">Watch this on YouTube</a>
</div>
<p>You&rsquo;ve probably used Claude or ChatGPT in a browser or app. You type a message, it responds, you ask it for something, it generates documents and content for you. But then you have to download it, copy and paste it, put it where it needs to go. That&rsquo;s useful, but it&rsquo;s limited by how quickly you can move data back and forth between what it&rsquo;s building, the notes you&rsquo;re feeding it, and the places you&rsquo;re testing and checking its work.</p>
<p>You may have also used coding assistants like GitHub Copilot or Cursor. These go further: they can see the context of actual code in a folder or repository, and they&rsquo;re not just making suggestions, they&rsquo;re writing code for you. You might have even used Claude as the model behind Copilot. But the AI is still limited to what you give it, either as explicit context or what&rsquo;s in that project folder.</p>
<p>Claude Code is different. It&rsquo;s Anthropic&rsquo;s command-line tool that runs as an agent on your machine. It can read files anywhere on your system, write code, run commands, make API calls, and interact with tools. It&rsquo;s not scoped to a single folder or IDE (unless you scope it yourself). Think of it less like a chatbot and more like a collaborator who can actually operate your computer. Depending on the access and tools you give it, it can do most of what you&rsquo;d do at a terminal yourself.</p>
<p>The name &ldquo;Claude Code&rdquo; is a bit misleading. Yes, it&rsquo;s great at coding. But it&rsquo;s also great at everything else: writing, research, file management, automation, building tools. It&rsquo;s really more of a personal AI assistant that happens to run in a terminal. The name will probably evolve, but for now, that&rsquo;s what we&rsquo;ve got, and it works really well.</p>
<p>A lot of people run Claude Code directly on their personal machines, whether that&rsquo;s Mac, Windows, or Linux. That can be a valid choice once you understand what it can do, how to limit it, and how to protect your data and system. But I&rsquo;m choosing to run mine in a Linux VM for now. I have too much sensitive stuff accessible from my main computer, and while I&rsquo;m in this exploratory learning-and-building mode with Claude, I don&rsquo;t want to have to monitor its every move the way I would on my personal machine. A more contained environment lets me learn faster with less anxiety. And Linux VMs are something I&rsquo;m comfortable setting up and managing.</p>
<p>Claude Code is very capable on its own. You can teach it a lot just with text files, folders, and structure. But here&rsquo;s the thing about this current realm of AI LLMs we&rsquo;ve got: the more information you load into a conversation, the more it has to juggle at once, and at some point that starts to limit what it can effectively do. So you don&rsquo;t want to overwhelm it. You want to guide it in the right direction for whatever you&rsquo;re working on, loading in just what it needs at any given time.</p>
<p><img alt="Evolution of AI capabilities" loading="lazy" src="/img/posts/pai-setup/evolution.jpg"></p>
<p>This is where structure really helps. Claude Code has a way of loading context on demand. You can have tons of information about how to do different types of tasks, organized into skills and workflows and folders, and Claude can choose what to load based on what you&rsquo;re actually asking it to do. That means you get the benefit of all that knowledge without stuffing everything into every conversation.</p>
<p>You can build this structure yourself, or you can use someone else&rsquo;s that they&rsquo;ve figured out works well. There are probably thousands of different approaches out there. People are publishing their workflows on YouTube, Reddit, and blogs all the time. They&rsquo;re all worth exploring to see what resonates with you.</p>
<p>What has worked really well for me is a project called PAI (Personal AI Infrastructure) by Daniel Miessler. It immediately adds structure on top of Claude Code: skills, workflows, hooks, customization. It helps Claude think and respond in ways that match how I want to work. That might sound vague right now, but it&rsquo;ll make a lot more sense once you start playing with it.</p>
<p>That&rsquo;s what this article and the accompanying video are for: to help you get started playing with it, and to do that in a safer way than just installing it directly on your main computer. Once you have it running, you can go back and read Daniel&rsquo;s <a href="https://danielmiessler.com/blog/personal-ai-infrastructure" target="_blank" rel="noopener noreferrer">really excellent article on PAI</a>
 to understand the philosophy and architecture. The concepts will land much better once you&rsquo;ve actually used the system.</p>
<p>One note: both PAI and Claude Code evolve quickly. Daniel pushes updates regularly, and I pull those into my system and adapt them. And who knows, some of this infrastructure might even get built into Claude Code itself in a few months. But this is what I&rsquo;m using now, and I&rsquo;ll try to update this guide or this series as things change.</p>
<h2 id="why-a-vm">Why a VM?</h2>
<p>Claude Code runs commands, writes files, and makes API calls. That&rsquo;s what makes it powerful. It&rsquo;s also why I&rsquo;d recommend starting in a contained environment.</p>
<p><img alt="A contained environment for safe experimentation" loading="lazy" src="/img/posts/pai-setup/sandbox.jpg"></p>
<p>A Linux VM gives you room to experiment without worrying about your main system. You can let Claude run more freely, see what it&rsquo;s capable of, and develop your own comfort level over time. You also get space to understand the security settings, learn how to limit things, and understand what you&rsquo;re saying &ldquo;yes&rdquo; to when you grant permissions.</p>
<p>You might even eventually move it to your main machine. But starting in a VM gives you the room to learn first.</p>
<h2 id="prerequisites">Prerequisites</h2>
<p>Before we start, you&rsquo;ll need:</p>
<ul>
<li>A Linux environment (one of the following):
<ul>
<li>A VM on your computer</li>
<li>A Raspberry Pi 4/5 with 8GB RAM</li>
<li>An old computer you can wipe</li>
</ul>
</li>
<li>Terminal access (SSH if remote, or direct terminal access)</li>
<li>Basic command line comfort (or willingness to learn as you go, Claude can help!)</li>
<li>An Anthropic account with Claude Pro ($20/month)</li>
</ul>
<h3 id="setting-up-a-linux-environment">Setting Up a Linux Environment</h3>
<p>If you already have a hypervisor or home lab, you know what to do. If not, here are your options:</p>
<p><strong>Option 1: VM on your computer (recommended for most people)</strong></p>
<p>This is free, gives you the best performance, and keeps everything local.</p>
<ul>
<li><strong><a href="https://www.virtualbox.org/" target="_blank" rel="noopener noreferrer">VirtualBox</a>
</strong> - Free and open source, works on Windows, Mac, and Linux</li>
<li><strong><a href="https://mac.getutm.app/" target="_blank" rel="noopener noreferrer">UTM</a>
</strong> - Free, open source, Mac-native (recommended for Apple Silicon Macs)</li>
</ul>
<p>If you&rsquo;ve never set up a VM before, NetworkChuck has <a href="https://www.youtube.com/watch?v=wX75Z-4MEoM" target="_blank" rel="noopener noreferrer">an excellent video explaining what VMs are and how to set up VirtualBox</a>
. Ubuntu also has <a href="https://ubuntu.com/tutorials/how-to-run-ubuntu-desktop-on-a-virtual-machine-using-virtualbox" target="_blank" rel="noopener noreferrer">an official tutorial for running Ubuntu in VirtualBox</a>
.</p>
<blockquote>
<p><strong>Note on Ubuntu versions:</strong> These links may reference an older version of Ubuntu. The recommended current version as of this writing is <strong>Ubuntu Server 24.04 LTS</strong>. <a href="https://ubuntu.com/download/server" target="_blank" rel="noopener noreferrer">Download Ubuntu Server</a>
 and select your architecture (AMD64 for Intel/AMD, ARM64 for Apple Silicon).</p></blockquote>
<blockquote>
<p><strong>Note for Mac users:</strong> NetworkChuck&rsquo;s video covers AMD64 (Intel/AMD) setups, including BIOS settings for virtualization. On Apple Silicon Macs, you don&rsquo;t need to change any BIOS settings. VirtualBox works, but UTM is generally smoother. Either way, download the <strong>ARM64</strong> version of Ubuntu, not the standard AMD64 image.</p></blockquote>
<p><strong>Option 2: Raspberry Pi or old computer</strong></p>
<p>A Raspberry Pi 4 or 5 with 8GB RAM works well. So does any old computer you can wipe and install Linux on. This gives you a dedicated always-on system.</p>
<p><strong>Option 3: Cloud VPS (advanced)</strong></p>
<p>Cloud providers like DigitalOcean, Linode, or Vultr work, but introduce additional complexity: you&rsquo;ll need to configure firewalls, consider HTTPS for any web content, and manage a publicly-accessible server. If you&rsquo;re comfortable with that, go for it. Otherwise, start local.</p>
<p><strong>What to install:</strong></p>
<p>I recommend <strong>Ubuntu Server 24.04 LTS</strong>. It&rsquo;s well-documented, beginner-friendly, and the installer walks you through creating a non-root user with sudo access (which is what you want). Skip the desktop environment; you&rsquo;ll be working at the command line.</p>
<p><strong>Before continuing:</strong></p>
<p>You should be at a command line in your VM, logged in as a non-root user that has sudo access. Ubuntu creates this during installation. If you&rsquo;re using Debian or another distro that defaults to root only, <a href="https://www.digitalocean.com/community/tutorials/how-to-create-a-new-sudo-enabled-user-on-ubuntu" target="_blank" rel="noopener noreferrer">here&rsquo;s how to create a sudo-enabled user</a>
 (the steps work on Debian too).</p>
<blockquote>
<p><strong>Tip:</strong> You probably already have access to Claude in your web browser, or another AI assistant. If you get stuck at any point, they can be really helpful for figuring out specific steps. Just tell them where you are and what you&rsquo;re trying to do.</p></blockquote>
<h2 id="a-note-on-curl--bash">A Note on curl | bash</h2>
<p>You&rsquo;re about to see a few commands that look like <code>curl ... | bash</code>. This pattern downloads a script from the internet and runs it directly on your machine. Security folks tend to cringe at this pattern, and for good reason. It&rsquo;s not something you&rsquo;d normally do on a production system or a machine with sensitive data.</p>
<p><img alt="Code from the internet entering your terminal" loading="lazy" src="/img/posts/pai-setup/download-terminal.jpg"></p>
<p>That&rsquo;s part of why we set up this VM. In a contained environment, you can be a <em>little</em> less cautious. But also these particular sources (Anthropic&rsquo;s installer, Bun&rsquo;s installer) are generally trustworthy. But it&rsquo;s worth noticing what you&rsquo;re doing: you&rsquo;re running code from the internet based on trust in the source.</p>
<p>We&rsquo;ll come back to this idea later, because there&rsquo;s an interesting parallel when we start giving Claude instructions from external sources.</p>
<h2 id="step-1-install-dependencies">Step 1: Install Dependencies</h2>
<p>We only need a couple things to get started:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo apt-get update <span style="color:#ff79c6">&amp;&amp;</span> sudo apt-get install -y curl git zip
</span></span></code></pre></div><h2 id="step-2-install-claude-code">Step 2: Install Claude Code</h2>
<p>Anthropic provides an <a href="https://claude.com/product/claude-code" target="_blank" rel="noopener noreferrer">official installer</a>
:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>curl -fsSL https://claude.ai/install.sh | bash
</span></span></code></pre></div><p>When the installer finishes, it will ask you to add Claude to your PATH. Run this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#8be9fd;font-style:italic">echo</span> <span style="color:#f1fa8c">&#39;export PATH=&#34;$HOME/.local/bin:$PATH&#34;&#39;</span> &gt;&gt; ~/.bashrc
</span></span></code></pre></div><h2 id="step-3-install-bun">Step 3: Install Bun</h2>
<p><a href="https://bun.sh" target="_blank" rel="noopener noreferrer">Bun</a>
 is a fast JavaScript runtime that Claude Code uses for various tools:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>curl -fsSL https://bun.sh/install | bash
</span></span></code></pre></div><h2 id="step-4-load-the-new-commands">Step 4: Load the New Commands</h2>
<p>Both installers added themselves to your shell configuration so you can type simple commands like <code>claude</code> and <code>bun</code> to launch things. Load them:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#8be9fd;font-style:italic">source</span> ~/.bashrc
</span></span></code></pre></div><p>Verify everything works:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>claude --version
</span></span><span style="display:flex;"><span>bun --version
</span></span></code></pre></div><h2 id="step-5-install-pai">Step 5: Install PAI</h2>
<p>Now we add the scaffolding that turns Claude Code into something more powerful.</p>
<p><strong>If you already have Claude Code settings you want to keep</strong>, back them up first:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#ff79c6">[</span> -d ~/.claude <span style="color:#ff79c6">]</span> <span style="color:#ff79c6">&amp;&amp;</span> mv ~/.claude ~/.claude-backup-<span style="color:#ff79c6">$(</span>date +%Y%m%d<span style="color:#ff79c6">)</span>
</span></span></code></pre></div><p>Clone the PAI repository and install the latest release:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git clone https://github.com/danielmiessler/PAI.git
</span></span><span style="display:flex;"><span>cp -r PAI/Releases/<span style="color:#ff79c6">$(</span>ls PAI/Releases/ | sort -V | tail -1<span style="color:#ff79c6">)</span>/.claude ~/
</span></span><span style="display:flex;"><span><span style="color:#8be9fd;font-style:italic">cd</span> ~/.claude <span style="color:#ff79c6">&amp;&amp;</span> sed -i <span style="color:#f1fa8c">&#39;s/--mode gui/--mode cli/&#39;</span> install.sh <span style="color:#ff79c6">&amp;&amp;</span> bash install.sh
</span></span></code></pre></div><p>This gives you a full copy of PAI in your home folder. You can browse it, reference it, and pull updates later.</p>
<p>The installer will auto-detect your system and check for dependencies. Since you already installed everything above, it will find Git, Bun, and Claude Code and move on.</p>
<p>The wizard will ask you a few questions. Here&rsquo;s what to enter:</p>
<ul>
<li><strong>What is your name?</strong> - Your name</li>
<li><strong>Timezone</strong> - It auto-detects this. Press Enter to confirm.</li>
<li><strong>Name your AI assistant</strong> - Whatever you want (default is PAI, I call mine Assistant)</li>
<li><strong>Startup catchphrase</strong> - Press Enter for default, or customize it</li>
<li><strong>Projects directory</strong> - Press Enter to skip</li>
<li><strong>Voice setup</strong> - When it asks about ElevenLabs, choose &ldquo;Skip voice for now.&rdquo; It will still try to configure voice defaults. Accept the default voice, then when it asks again, choose skip. We don&rsquo;t need voice for this setup.</li>
</ul>
<h2 id="step-6-fix-shell-configuration">Step 6: Fix Shell Configuration</h2>
<p>The PAI installer writes to <code>.zshrc</code> (the default shell on macOS), but Ubuntu uses bash. These commands merge any zsh config into your bash config and fix a path issue in the current release:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#ff79c6">[</span> -f ~/.zshrc <span style="color:#ff79c6">]</span> <span style="color:#ff79c6">&amp;&amp;</span> cat ~/.zshrc &gt;&gt; ~/.bashrc
</span></span><span style="display:flex;"><span>sed -i <span style="color:#f1fa8c">&#39;s|skills/PAI/Tools/pai.ts|PAI/Tools/pai.ts|g&#39;</span> ~/.bashrc
</span></span><span style="display:flex;"><span><span style="color:#8be9fd;font-style:italic">source</span> ~/.bashrc
</span></span></code></pre></div><p>The <code>sed</code> line fixes a known issue where the installer writes the <code>pai</code> alias pointing to the wrong path. Without it, running <code>pai</code> will fail with a &ldquo;Module not found&rdquo; error.</p>
<h2 id="step-7-first-run-and-authentication">Step 7: First Run and Authentication</h2>
<p>Now launch Claude Code with PAI:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>pai
</span></span></code></pre></div><p>The first time you run it, you&rsquo;ll walk through a few prompts:</p>
<p><strong>Color scheme:</strong> Pick dark mode, light mode, or a color-blind friendly version of each.</p>
<p><strong>Login method:</strong> Select &ldquo;Claude Account (with Subscription)&rdquo;. This is where you&rsquo;ll need that Claude Pro account. If you don&rsquo;t have one yet, head over to <a href="https://claude.ai" target="_blank" rel="noopener noreferrer">claude.ai</a>
 to sign up. The other login methods will likely cost you more money since they use API credits directly.</p>
<p><strong>Browser authentication:</strong> It will say &ldquo;Opening browser to sign in&rdquo; but that won&rsquo;t work since you&rsquo;re in a VM. Instead, copy that long URL it displays. Paste it into a new tab in your web browser. Sign into Claude there (or if you&rsquo;re already signed in, it will just ask you to authorize). Click Authorize, copy the code it gives you, and paste it back into the terminal where it says &ldquo;Paste code here.&rdquo;</p>
<p><strong>Login successful:</strong> Hit Enter to continue.</p>
<p><strong>Safety warning:</strong> It will warn you that Claude can make mistakes and that you need to review what it does. This is part of why we&rsquo;re running it in a VM, right? We&rsquo;re not giving it access to anything sensitive until we&rsquo;re comfortable with how it works.</p>
<p><strong>Trust folder:</strong> It will ask if you trust the <code>.claude</code> folder. You&rsquo;ll need to choose &ldquo;Yes, I trust this folder&rdquo; to use PAI.</p>
<p>And then you&rsquo;re in. You should see an interactive prompt. Try this to make sure everything is working:</p>
<blockquote>
<p>&ldquo;What&rsquo;s my name and what skills do you know?&rdquo;</p></blockquote>
<p>It should know your name (from the wizard) and list a couple dozen skills that come with PAI out of the box. If you see that, you&rsquo;re ready for the next step.</p>
<h2 id="step-8-adapt-pai-for-linux">Step 8: Adapt PAI for Linux</h2>
<p>PAI was built on macOS, so there are a few more things that need patching for Linux. Here&rsquo;s where it gets interesting.</p>
<p>Paste this into the prompt:</p>
<blockquote>
<p>Read this URL and follow the instructions to adapt PAI for Linux: <a href="https://gist.githubusercontent.com/chriscantey/50523c88bc54663916481882f3e3c704/raw/pai-linux-adaptation.md" target="_blank" rel="noopener noreferrer">https://gist.githubusercontent.com/chriscantey/50523c88bc54663916481882f3e3c704/raw/pai-linux-adaptation.md</a>
</p></blockquote>
<p>Your Assistant (Claude + PAI) will read the file, patch the statusline for Linux compatibility, and add a steering rule so web servers provide accessible URLs instead of localhost.</p>
<p><strong>A note on what just happened:</strong> This &ldquo;read a URL and follow the instructions&rdquo; pattern is powerful. It&rsquo;s also a good example of why you want to be thoughtful about what you point your AI at.</p>
<p><img alt="The trust chain from you to Claude to external sources" loading="lazy" src="/img/posts/pai-setup/trust-chain.jpg"></p>
<p>Remember earlier when we talked about <code>curl | bash</code>? That&rsquo;s running code from the internet based on trust. This is similar, but instead of code, it&rsquo;s instructions for an AI that has access to your system. If that file contained malicious instructions, your Assistant might try to follow them.</p>
<p>From the outside, these might seem like the same risk, but there&rsquo;s an important difference. A shell script can be more predictable. You can read it and see exactly what it will do. It&rsquo;s traditional programming: the same script run twice will do the same thing.</p>
<p>An AI agent is different. Ask it to do the same task twice and it might take different approaches. Run it on a different system, with a different person, against a different backend, or with a future version of Claude, and the behavior may vary. That flexibility is what makes agents powerful, but it also means there&rsquo;s more room for them to interpret, improvise, and find creative paths to a goal. Great when you want that, less great when someone&rsquo;s trying to trick them.</p>
<p>This is one example of what&rsquo;s sometimes called <em>prompt injection</em>: content designed to manipulate an AI&rsquo;s behavior.</p>
<p>When your Assistant searches the web, reads files, or fetches URLs, it might encounter instructions embedded in that content. The same way you give it instructions, someone else could sneak instructions into a webpage the Assistant reads, and the Assistant might follow them without realizing they came from an untrusted source.</p>
<p>PAI has some hooks and protections in place to prevent certain things from happening, and running as a non-root user adds another layer. But these are layers, not guarantees. The contained environment we set up is part of the overall approach: you can learn how this works, build comfort over time, and be more thoughtful about what you expose it to as you expand its access.</p>
<p>More on security practices in a future post.</p>
<h2 id="what-you-have-now">What You Have Now</h2>
<p>At this point, you have:</p>
<ul>
<li>Claude Code running on Linux</li>
<li>PAI&rsquo;s skill system loaded</li>
<li>Linux-specific patches applied</li>
</ul>
<p>You can start exploring. Type <code>/help</code> to see available commands. Try invoking a skill. Break things. Rebuild.</p>
<h2 id="try-it-build-something">Try It: Build Something</h2>
<p>The best way to understand what your Assistant can do is to build something with it. Here&rsquo;s a quick one you can try. Paste this into the prompt (replace the city with your own):</p>
<blockquote>
<p>Build me a simple web page that shows the current weather for [insert your city name here]. Use a free and open weather API that doesn&rsquo;t require an API key. Fetch the current conditions and display them in a modern, nice looking page with a dark background. Serve it so I can view it in my browser.</p></blockquote>
<p>You&rsquo;re going to see a lot of stuff fly by, especially if you&rsquo;re not used to watching code. That&rsquo;s okay. Watch as it works through the problem: searching for weather APIs, writing HTML, fetching live data, spinning up a server. Part of what PAI adds to Claude Code is all this thinking and verification, making sure it&rsquo;s actually achieving what you asked for. If it hits a problem, it&rsquo;ll try to fix it or help you understand what went wrong. It might take a little while, especially the first time. When it gives you a URL, open it in your browser. You should see your weather page, built from scratch, running live.</p>
<p>It <em>might</em> also do something interesting: download tools it needs to help you. For example, it may install Playwright and Chromium so it can open a browser and verify its own work. Notice I said &ldquo;might.&rdquo; Running the same prompt on two different systems, one time it did its own verification, another time it didn&rsquo;t. That&rsquo;s the nature of these systems. It&rsquo;s also a little spooky when it just downloads apps on its own. That&rsquo;s why we&rsquo;re in a VM.</p>
<p>That&rsquo;s the difference between a chatbot and an agent. The chatbot would give you code to copy, or possibly a preview. Your Assistant actually builds the thing and runs it. And if you give it the right access, it can put that page online for you, all in one go. Then you can work back and forth with it to add features, change the design, and build on it over time. All without the copying and pasting.</p>
<h2 id="where-to-go-from-here">Where to Go From Here</h2>
<p>Spend some time with it. Point it at some data you&rsquo;re comfortable experimenting with. Think about something you&rsquo;ve been wanting to build: a tool, a design, a dashboard, a 3D model, really anything is worth a try. It&rsquo;s running on a computer, so it can run the same tools you&rsquo;d run yourself, and in many cases it can grab new tools to work with.</p>
<p>If you want the deep dive on the philosophy and architecture, read <a href="https://danielmiessler.com/blog/personal-ai-infrastructure" target="_blank" rel="noopener noreferrer">Daniel&rsquo;s PAI article</a>
. The concepts will land better now that you&rsquo;ve seen the system in action.</p>
<p>This is the first in a series. I&rsquo;ll be posting more about security practices, building custom skills, and how I&rsquo;m using this system in my own work. Subscribe or check back if you want to follow along.</p>
<h2 id="resources">Resources</h2>
<ul>
<li><a href="https://danielmiessler.com/blog/personal-ai-infrastructure" target="_blank" rel="noopener noreferrer">Daniel Miessler&rsquo;s PAI Article</a>
 - The complete system overview and philosophy</li>
<li><a href="https://github.com/danielmiessler/pai" target="_blank" rel="noopener noreferrer">PAI GitHub</a>
 - Source repo with releases, skills, and documentation</li>
<li><a href="https://github.com/danielmiessler/pai/releases" target="_blank" rel="noopener noreferrer">PAI Releases</a>
 - The install command above automatically uses the latest release</li>
<li><a href="https://gist.github.com/chriscantey/50523c88bc54663916481882f3e3c704" target="_blank" rel="noopener noreferrer">Linux adaptation gist</a>
 - The Linux adaptation instructions from Step 8</li>
<li><a href="https://www.youtube.com/watch?v=wX75Z-4MEoM" target="_blank" rel="noopener noreferrer">NetworkChuck&rsquo;s VM video</a>
 - Great intro to VMs and VirtualBox setup</li>
<li><a href="https://ubuntu.com/tutorials/how-to-run-ubuntu-desktop-on-a-virtual-machine-using-virtualbox" target="_blank" rel="noopener noreferrer">Ubuntu VirtualBox tutorial</a>
 - Official guide for running Ubuntu in VirtualBox</li>
</ul>
<hr>
<p><em>This guide is current as of PAI v4.0 (February 2026). PAI evolves quickly, so some details may change.</em></p>
]]></content:encoded>
    </item>
    <item>
      <title>The Many AIs, My Evolving Approach</title>
      <link>https://chriscantey.com/posts/2026-01-25-my-thoughts-on-ai/</link>
      <pubDate>Sun, 25 Jan 2026 00:00:00 +0000</pubDate>
      <guid>https://chriscantey.com/posts/2026-01-25-my-thoughts-on-ai/</guid>
      <description>There isn&amp;#39;t just one AI. There are dozens of different things all wearing the same name.</description>
      <content:encoded><![CDATA[<p>Here&rsquo;s what keeps coming up for me about AI: we&rsquo;re calling a lot of different things by the same name.</p>
<p>There are the tools themselves. ChatGPT, Claude, Gemini, Copilot. Image generators like Midjourney, DALL-E, Stable Diffusion. Voice cloning, video synthesis, coding assistants. A dozen categories of software, all lumped under one umbrella term.</p>
<p>But there&rsquo;s another layer that I think matters just as much: the <em>perspectives</em> people bring when they talk about AI. How you feel about these tools depends a lot on where you&rsquo;re standing. Whether you see opportunity or threat, convenience or risk, the future of work or the end of it. We&rsquo;re not just using different tools; we&rsquo;re coming at this from completely different places. And I think that&rsquo;s shaping adoption, trust, and the conversations we&rsquo;re having about what AI should and shouldn&rsquo;t do.</p>
<p>So I want to try and break down both: the many things we&rsquo;re calling AI, and the different lenses through which people see them. This list isn&rsquo;t comprehensive, and I expect my thinking will keep shifting as this whole landscape does.</p>
<h2 id="the-many-faces-of-ai">The Many Faces of AI</h2>
<p>When someone says &ldquo;AI&rdquo; to me now, the first thing I&rsquo;m thinking is: which one?</p>
<p>There&rsquo;s <strong>search-replacement AI</strong>, whether that&rsquo;s ChatGPT, Claude, Gemini, or the AI summaries that now appear at the top of Google results. A lot of people use these the same way they used to use search engines: ask a question, get an answer. The convenience is undeniable. But so is the confidence problem. These tools can be wrong, cite sources that don&rsquo;t say what they claim, or just make things up entirely. They deliver answers with the same tone whether they&rsquo;re right or completely off. That&rsquo;s a strange new dynamic to navigate.</p>
<p>There&rsquo;s <strong>boardroom buzzword AI</strong>, the one that executives drop into quarterly reports. It&rsquo;s a checkbox. A signal that the company is &ldquo;innovative.&rdquo; Sometimes there&rsquo;s real substance behind it, and sometimes it&rsquo;s more about optics than implementation. I&rsquo;ve seen both.</p>
<p>There&rsquo;s <strong>coding AI</strong>, helping developers write software faster and helping people with no programming background build things they couldn&rsquo;t have built before. &ldquo;Vibe coding&rdquo; is what some people call it: describing what you want and letting the AI figure out the implementation. It&rsquo;s genuinely cool to see people bring ideas to life that would have stayed stuck in their heads otherwise. But it comes with responsibility: we have to stay mindful of where any unreviewed AI-generated code ends up running in production.</p>
<p>There&rsquo;s <strong>job-fear AI</strong>. The version that has people wondering whether their job will exist in five years. Writing, coding, design, analysis, customer service. The automation question isn&rsquo;t new, but AI has expanded the scope of what might be automated. I&rsquo;ve worked in and around creative industries for most of my career, and I watch friends and former colleagues grapple with this one. When your livelihood feels threatened, you don&rsquo;t want nuance. You want clarity. The people who are cautious about these tools aren&rsquo;t wrong to be. They&rsquo;re protecting something real. And honestly? AI might be coming for my work next. I don&rsquo;t think anyone is immune from that question right now.</p>
<p>There&rsquo;s <strong>slop-generating AI</strong>, pumping out endless content that nobody asked for. Low-quality articles, spam images, fake reviews. The internet already had a noise problem, and some of these tools are making it worse. Then there&rsquo;s the content people think is real but isn&rsquo;t. AI-generated entertainment is one thing. But fake videos, fabricated quotes, and voice clones designed to manipulate? That&rsquo;s something else entirely.</p>
<p>There&rsquo;s <strong>plagiarism and copyright AI</strong>, trained on other people&rsquo;s work without clear permission or compensation. Artists, writers, and creators have legitimate frustrations here. The legal and ethical questions are far from settled, and I don&rsquo;t think we should pretend they are.</p>
<p>There&rsquo;s <strong>environmental-concern AI</strong>. These systems can consume significant amounts of power, and depending on the facility and location, water for cooling. That&rsquo;s not fear-mongering; the resource demands are real. But it&rsquo;s also more nuanced than some headlines suggest. Some data centers are moving to zero-water cooling systems, while others in water-stressed regions are drawing millions of gallons daily. Whether the tradeoffs are worth it probably depends on what&rsquo;s being accomplished with that compute.</p>
<p>There&rsquo;s <strong>creepy surveillance AI</strong>, feeding facial recognition systems, risk-scoring algorithms, behavioral tracking, and data harvesting that gets packaged and sold. These tools power monitoring, manipulation, and control, often without the knowledge of the people being watched, scored, or profiled. Privacy erosion at scale, and once it&rsquo;s gone, it doesn&rsquo;t come back easily.</p>
<p>There&rsquo;s <strong>medical and research AI</strong>, the kind that helps scientists analyze data, discover drugs, identify diseases earlier, and push forward in ways that would take humans decades longer. When AI helps catch a cancer earlier or accelerates vaccine development, that&rsquo;s the version of this technology I want to see more of.</p>
<p>There&rsquo;s <strong>security defense AI</strong>, and this one hits close to home for me. These tools can help security teams detect threats faster, triage alerts that would otherwise pile up, and give smaller teams capabilities that used to require much larger headcounts. It&rsquo;s not a silver bullet, but it can genuinely make a difference for people trying to protect systems and data.</p>
<p>There&rsquo;s <strong>cybercrime AI</strong>, the kind that helps bad actors craft more convincing phishing emails, find vulnerabilities faster, and automate attacks that used to take longer and in some cases more expertise. Working in cybersecurity, I see this one up close. The same capabilities that help defenders also help attackers, and that arms race is accelerating.</p>
<p>And then there&rsquo;s the one I actually use every day: <strong>practical workflow AI</strong>. The tools that help me get more done, think through problems, and extend what I&rsquo;m capable of.</p>
<blockquote>
<p>And all of this is to say nothing about the machine learning that&rsquo;s been quietly running in the background for years: Siri and Alexa, autocorrect, spam filters, photo face recognition, recommendation algorithms, fraud detection, GPS route optimization, robovacuums. We&rsquo;ve been living with &ldquo;AI&rdquo; for a long time without the cultural weight the term carries now. What I&rsquo;m talking about here is really the current moment, the strange dichotomy the word has taken on in our society.</p></blockquote>
<h2 id="where-ive-landed-for-now">Where I&rsquo;ve Landed (For Now)</h2>
<p>I&rsquo;m using AI to improve my workflows, increase what I can accomplish, and do more for my clients. It&rsquo;s not an abstract concept for me anymore. It&rsquo;s integrated into how I work.</p>
<p>In practice, that looks like a few different things. I&rsquo;ve always been big on communication: presentations, videos, reports for clients. That work takes time, and I used to do less of it because each piece was a production. Now I can take the data and ideas I&rsquo;m working with and turn them into polished deliverables much faster. Three or four times as much output in the same window.</p>
<p>It helps me manage large implementation projects for clients, tracking the dozens of moving pieces that come with any serious technical engagement. It helps me build tools, including ones I can send to a 3D printer. It helps me build and manage the self-hosted services I run in my own lab. It connects into my calendar, my task lists, my documents, and helps me stay on top of a growing number of coding projects and automations.</p>
<p>And it&rsquo;s let me tiptoe into areas I&rsquo;m still new to. I&rsquo;ve started experimenting with custom hardware, building small devices that integrate with my automation systems. I&rsquo;m not a hardware hacker by background, but having something that can help me bridge the gap between what I know and what I&rsquo;m trying to learn has made that kind of experimentation feel possible.</p>
<p>The way I use it keeps shifting. A year ago it was mostly standalone conversations. Now it&rsquo;s more embedded, connected to the systems I already use, doing real work alongside me.</p>
<p>And even within the tools themselves, I&rsquo;m not locked into one. Right now I&rsquo;m using Claude Code with a lot of customization layered on top. But over the past few years I&rsquo;ve moved between Claude in the browser, ChatGPT, local LLMs, various image generators, different voice tools. My approach has been to build my workflows so they can sit on top of whichever tool is giving me the best results at any given time. None of this is static, and neither is my setup.</p>
<p>And here&rsquo;s the weird part: when I&rsquo;m actually using it, I stop thinking about it as &ldquo;AI.&rdquo; It&rsquo;s just a thing that can do work. I hand tasks to something that understands what I&rsquo;m trying to accomplish. It becomes another way to build processes and applications, kind of independent of all the hype and fear around the term itself.</p>
<p><a href="https://danielmiessler.com/blog/personal-ai-infrastructure#personal-augmentation" target="_blank" rel="noopener noreferrer">Daniel Miessler</a>
, whose work I&rsquo;ve been following closely for a while, puts it this way:</p>
<blockquote>
<p>&ldquo;The main practical theme of what I look to do with a system like this is to augment myself. Like, massively, with insane capabilities. Think Tony Stark stuff, no joke. Minus the flying. It&rsquo;s about doing the things that you wish you could do that you never could do before, like having a team of 1,000 or 10,000 people working for you on your own personal and business goals.&rdquo;</p></blockquote>
<p>That really resonates with me. Not because I think AI is magic or harmless, but because I&rsquo;ve experienced what it feels like to have capabilities I didn&rsquo;t have before. To build things I couldn&rsquo;t have built alone. To work on problems that would have taken me weeks.</p>
<h2 id="the-uncertainty">The Uncertainty</h2>
<p>AI and all of this related technology is reshaping the economy and work, and likely will continue to. We&rsquo;re going to see huge changes over the coming years with what these agents are capable of, the automations they enable, and the way they integrate into our devices and daily work.</p>
<p>A lot depends on how smart these systems get, how fast they get there, and what we decide to give them access to. And by &ldquo;them&rdquo; I mean all of them, because there isn&rsquo;t just one AI making these decisions. There are thousands of systems, developed by different companies, with different goals, being deployed in different contexts. The future isn&rsquo;t one story. It&rsquo;s a thousand stories playing out at once.</p>
<p>I&rsquo;m more hopeful than anything, honestly. It&rsquo;s just a matter of how things shake out, and how well (or how badly) the big tech companies, governments, and all of us handle what&rsquo;s being built.</p>
<p>And who knows? We may not even have access to these tools in the same way a year from now. The costs, availability, and capabilities could shift completely. But for the time being, I&rsquo;m really enjoying using what&rsquo;s available to do better work.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Welcome to Here</title>
      <link>https://chriscantey.com/posts/2026-01-24-welcome/</link>
      <pubDate>Sat, 24 Jan 2026 00:00:00 +0000</pubDate>
      <guid>https://chriscantey.com/posts/2026-01-24-welcome/</guid>
      <description>What this is about and why I&amp;#39;m adding another website to the internet.</description>
      <content:encoded><![CDATA[<p>I&rsquo;ve been meaning to do this for about a decade.</p>
<p>Not this exact site, but something like it. A place to share what I&rsquo;m working on, what I&rsquo;m thinking about, and what I&rsquo;ve learned along the way. I&rsquo;ve started and stopped a few times over the years, but it never stuck. Life got busy, projects piled up, and the idea of maintaining a blog always fell to the bottom of the list.</p>
<p>So why now?</p>
<p>Honestly, a big part of it is that AI tools have made it easier to actually capture and share what I&rsquo;m doing. Not in a &ldquo;the robots write my posts&rdquo; way, but in a &ldquo;I can finally get my thoughts out of my head and onto a page without it feeling like a second job&rdquo; way. The friction is lower. The barrier is smaller. And that&rsquo;s been enough to tip the scales.</p>
<p>This blog will probably have a lot of AI-related content, because that&rsquo;s what I&rsquo;m currently obsessed with. But it won&rsquo;t just be AI stuff. I have a lot of hobbies. I build things. I tinker. I&rsquo;m a cybersecurity consultant by trade, but I&rsquo;ve also got a film scanner I 3D-printed, a coffee roasting setup, home automation projects, and whatever else catches my attention.</p>
<p>The core concept here is using technology to improve my life, and then sharing what works (and what doesn&rsquo;t). Sometimes that&rsquo;ll be AI. Sometimes it&rsquo;ll be a weird 3D printing project. Sometimes it&rsquo;ll just be me rambling about something I find interesting.</p>
<p>Let&rsquo;s see where this goes.</p>
]]></content:encoded>
    </item>
    <item>
      <title>About</title>
      <link>https://chriscantey.com/about/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://chriscantey.com/about/</guid>
      <description>&lt;div style=&#34;text-align: center; margin-bottom: 1.5rem;&#34;&gt;
  &lt;img src=&#34;https://chriscantey.com/img/ProfilePhotoCC.webp&#34; alt=&#34;Chris Cantey&#34; style=&#34;width: 150px; height: 150px; border-radius: 50%; object-fit: cover;&#34;&gt;
&lt;/div&gt;
&lt;p&gt;Hey, I&amp;rsquo;m Chris Cantey. 👋&lt;/p&gt;
&lt;p&gt;I have a lot of hobbies. I build things. I tinker. These days I&amp;rsquo;ve got a film scanner I 3D-printed, a coffee roasting setup, home automation projects, and whatever else catches my attention. This site is where I share what I&amp;rsquo;m working on, what I&amp;rsquo;m thinking about, and what I&amp;rsquo;ve learned along the way.&lt;/p&gt;
&lt;p&gt;I live in Southern California with Rudy, a wiener dog who comes with me everywhere, and Magnus, a 15-year-old cat who prefers the couch.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<div style="text-align: center; margin-bottom: 1.5rem;">
  <img src="/img/ProfilePhotoCC.webp" alt="Chris Cantey" style="width: 150px; height: 150px; border-radius: 50%; object-fit: cover;">
</div>
<p>Hey, I&rsquo;m Chris Cantey. 👋</p>
<p>I have a lot of hobbies. I build things. I tinker. These days I&rsquo;ve got a film scanner I 3D-printed, a coffee roasting setup, home automation projects, and whatever else catches my attention. This site is where I share what I&rsquo;m working on, what I&rsquo;m thinking about, and what I&rsquo;ve learned along the way.</p>
<p>I live in Southern California with Rudy, a wiener dog who comes with me everywhere, and Magnus, a 15-year-old cat who prefers the couch.</p>
<p>By trade, I&rsquo;m a cybersecurity consultant. I run <a href="https://wonders.co" target="_blank" rel="noopener noreferrer">Wonders</a>
, where I help businesses simplify their tech and security. I also created <a href="https://hardertohack.com" target="_blank" rel="noopener noreferrer">Harder to Hack</a>
, a project focused on making personal cybersecurity accessible to everyone.</p>
<p>But really, I&rsquo;m just someone who likes figuring out how things work and making them better.</p>
<div style="display: flex; gap: 1.5rem; margin-top: 3rem; flex-wrap: wrap; justify-content: center;">
  <a href="https://youtube.com/@wondersco" target="_blank" rel="noopener noreferrer" style="flex: 1; min-width: 250px; max-width: 350px; padding: 1.5rem; background: rgba(28, 28, 42, 0.7); backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.05); border-radius: 12px; text-decoration: none; text-align: center;">
    <svg style="width: 3rem; height: 3rem; margin-bottom: 0.5rem; fill: rgb(217, 70, 239);" viewBox="0 0 24 24"><path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"/></svg>
    <div style="font-size: 1.1rem; font-weight: 600; color: rgb(245, 245, 250); margin-bottom: 0.5rem;">YouTube</div>
    <div style="font-size: 0.9rem; color: rgb(180, 180, 195);">More videos and walkthroughs.</div>
  </a>
  <a href="https://linkedin.com/in/chriscantey" target="_blank" rel="noopener noreferrer" style="flex: 1; min-width: 250px; max-width: 350px; padding: 1.5rem; background: rgba(28, 28, 42, 0.7); backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.05); border-radius: 12px; text-decoration: none; text-align: center;">
    <svg style="width: 3rem; height: 3rem; margin-bottom: 0.5rem; fill: rgb(217, 70, 239);" viewBox="0 0 24 24"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/></svg>
    <div style="font-size: 1.1rem; font-weight: 600; color: rgb(245, 245, 250); margin-bottom: 0.5rem;">LinkedIn</div>
    <div style="font-size: 0.9rem; color: rgb(180, 180, 195);">Connect with me professionally.</div>
  </a>
  <a href="https://github.com/chriscantey" target="_blank" rel="noopener noreferrer" style="flex: 1; min-width: 250px; max-width: 350px; padding: 1.5rem; background: rgba(28, 28, 42, 0.7); backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.05); border-radius: 12px; text-decoration: none; text-align: center;">
    <svg style="width: 3rem; height: 3rem; margin-bottom: 0.5rem; fill: rgb(217, 70, 239);" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23A11.509 11.509 0 0112 5.803c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222 0 1.606-.014 2.898-.014 3.293 0 .322.216.694.825.576C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>
    <div style="font-size: 1.1rem; font-weight: 600; color: rgb(245, 245, 250); margin-bottom: 0.5rem;">GitHub</div>
    <div style="font-size: 0.9rem; color: rgb(180, 180, 195);">Code and projects.</div>
  </a>
  <a href="https://instagram.com/chriswonders" target="_blank" rel="noopener noreferrer" style="flex: 1; min-width: 250px; max-width: 350px; padding: 1.5rem; background: rgba(28, 28, 42, 0.7); backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.05); border-radius: 12px; text-decoration: none; text-align: center;">
    <svg style="width: 3rem; height: 3rem; margin-bottom: 0.5rem; fill: rgb(217, 70, 239);" viewBox="0 0 24 24"><path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163C8.741 0 8.332.014 7.052.072 2.695.272.273 2.69.073 7.052.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98C8.333 23.986 8.741 24 12 24c3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 1 0 0 12.324 6.162 6.162 0 0 0 0-12.324zM12 16a4 4 0 1 1 0-8 4 4 0 0 1 0 8zm6.406-11.845a1.44 1.44 0 1 0 0 2.881 1.44 1.44 0 0 0 0-2.881z"/></svg>
    <div style="font-size: 1.1rem; font-weight: 600; color: rgb(245, 245, 250); margin-bottom: 0.5rem;">Instagram</div>
    <div style="font-size: 0.9rem; color: rgb(180, 180, 195);">Photos and behind the scenes.</div>
  </a>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>Newsletter</title>
      <link>https://chriscantey.com/newsletter/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://chriscantey.com/newsletter/</guid>
      <description>&lt;p&gt;I write about tech, security, and whatever I&amp;rsquo;m building or tinkering with. A few times a month I send out an update with what I&amp;rsquo;ve been writing, what I&amp;rsquo;m working on, and anything interesting I&amp;rsquo;ve come across. No spam, no marketing, no listicles.&lt;/p&gt;
&lt;p&gt;If that sounds like your kind of thing, drop your email below.&lt;/p&gt;
&lt;style&gt;.newsletter-section { display: none; }&lt;/style&gt;
&lt;div class=&#34;newsletter-content&#34; style=&#34;margin-top: 2rem;&#34;&gt;
  &lt;form class=&#34;newsletter-form&#34; id=&#34;newsletter-page-form&#34;&gt;
    &lt;input
      type=&#34;email&#34;
      name=&#34;email&#34;
      placeholder=&#34;you@example.com&#34;
      required
      autocomplete=&#34;email&#34;
      aria-label=&#34;Email address&#34;
    /&gt;
    &lt;button type=&#34;submit&#34;&gt;Subscribe&lt;/button&gt;
  &lt;/form&gt;
  &lt;p class=&#34;newsletter-status&#34; id=&#34;newsletter-page-status&#34; aria-live=&#34;polite&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div style=&#34;margin-top: 2rem; text-align: center;&#34;&gt;
  &lt;a href=&#34;https://buttondown.com/chriscantey/archive/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34; style=&#34;color: #c471ed; text-decoration: none; font-size: 0.95rem;&#34;&gt;Browse past issues →&lt;/a&gt;
&lt;/div&gt;
&lt;script&gt;
(function() {
  var form = document.getElementById(&#39;newsletter-page-form&#39;);
  var status = document.getElementById(&#39;newsletter-page-status&#39;);

  if (!form) return;

  form.addEventListener(&#39;submit&#39;, function(e) {
    e.preventDefault();

    var email = form.email.value.trim();
    var button = form.querySelector(&#39;button&#39;);

    status.textContent = &#39;&#39;;
    status.className = &#39;newsletter-status&#39;;

    button.disabled = true;
    button.textContent = &#39;Subscribing...&#39;;

    fetch(&#39;/api/subscribe&#39;, {
      method: &#39;POST&#39;,
      headers: { &#39;Content-Type&#39;: &#39;application/json&#39; },
      body: JSON.stringify({ email: email })
    })
    .then(function(response) {
      return response.json();
    })
    .then(function(data) {
      if (data.success) {
        status.textContent = data.message;
        status.className = &#39;newsletter-status success&#39;;
        form.reset();
      } else {
        status.textContent = data.error || &#39;Something went wrong.&#39;;
        status.className = &#39;newsletter-status error&#39;;
      }
    })
    .catch(function() {
      status.textContent = &#39;Unable to connect. Please try again.&#39;;
      status.className = &#39;newsletter-status error&#39;;
    })
    .finally(function() {
      button.disabled = false;
      button.textContent = &#39;Subscribe&#39;;
    });
  });
})();
&lt;/script&gt;</description>
      <content:encoded><![CDATA[<p>I write about tech, security, and whatever I&rsquo;m building or tinkering with. A few times a month I send out an update with what I&rsquo;ve been writing, what I&rsquo;m working on, and anything interesting I&rsquo;ve come across. No spam, no marketing, no listicles.</p>
<p>If that sounds like your kind of thing, drop your email below.</p>
<style>.newsletter-section { display: none; }</style>
<div class="newsletter-content" style="margin-top: 2rem;">
  <form class="newsletter-form" id="newsletter-page-form">
    <input
      type="email"
      name="email"
      placeholder="you@example.com"
      required
      autocomplete="email"
      aria-label="Email address"
    />
    <button type="submit">Subscribe</button>
  </form>
  <p class="newsletter-status" id="newsletter-page-status" aria-live="polite"></p>
</div>
<div style="margin-top: 2rem; text-align: center;">
  <a href="https://buttondown.com/chriscantey/archive/" target="_blank" rel="noopener" style="color: #c471ed; text-decoration: none; font-size: 0.95rem;">Browse past issues →</a>
</div>
<script>
(function() {
  var form = document.getElementById('newsletter-page-form');
  var status = document.getElementById('newsletter-page-status');

  if (!form) return;

  form.addEventListener('submit', function(e) {
    e.preventDefault();

    var email = form.email.value.trim();
    var button = form.querySelector('button');

    status.textContent = '';
    status.className = 'newsletter-status';

    button.disabled = true;
    button.textContent = 'Subscribing...';

    fetch('/api/subscribe', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email: email })
    })
    .then(function(response) {
      return response.json();
    })
    .then(function(data) {
      if (data.success) {
        status.textContent = data.message;
        status.className = 'newsletter-status success';
        form.reset();
      } else {
        status.textContent = data.error || 'Something went wrong.';
        status.className = 'newsletter-status error';
      }
    })
    .catch(function() {
      status.textContent = 'Unable to connect. Please try again.';
      status.className = 'newsletter-status error';
    })
    .finally(function() {
      button.disabled = false;
      button.textContent = 'Subscribe';
    });
  });
})();
</script>
]]></content:encoded>
    </item>
  </channel>
</rss>
