<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://ncvgl.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://ncvgl.github.io/" rel="alternate" type="text/html" /><updated>2026-04-24T11:10:42+00:00</updated><id>https://ncvgl.github.io/feed.xml</id><title type="html">My Blog</title><subtitle>Exploring the latest developments in artificial intelligence and machine learning</subtitle><author><name>Nathan Cavaglione</name></author><entry><title type="html">I Tested The Viral Caveman Prompt On 100 Coding Tasks</title><link href="https://ncvgl.github.io/posts/caveman-prompt-tested/" rel="alternate" type="text/html" title="I Tested The Viral Caveman Prompt On 100 Coding Tasks" /><published>2026-04-21T00:00:00+00:00</published><updated>2026-04-21T00:00:00+00:00</updated><id>https://ncvgl.github.io/posts/caveman-prompt-tested</id><content type="html" xml:base="https://ncvgl.github.io/posts/caveman-prompt-tested/"><![CDATA[<p><img src="/assets/images/caveman-mosaic.png" alt="Mosaic of 731 SWE-bench Pro Public instances ordered by difficulty. Each cell is split horizontally: top half = baseline, bottom half = caveman. Green = resolved, red = failed, gray = not tested. Our 101-instance frontier band appears as a colored stripe across the gray." style="max-width: 600px; width: 100%; height: auto; display: block; margin: 20px auto;" /></p>

<p><strong>Repo with all data, patches, and session transcripts:</strong> <a href="https://github.com/ncvgl/does-caveman-kill-claude">github.com/ncvgl/does-caveman-kill-claude</a></p>

<p>40,000 people starred the <a href="https://github.com/JuliusBrussee/caveman">caveman prompt</a>. It promises <strong>65% token savings</strong> by making LLMs talk like cavemen, with the slogan <em>“why use many token when few token do trick.”</em> Catchy, viral, fun.</p>

<p>So I tested it.</p>

<p><strong>Result: a marginal 14% on real coding tasks, not 65%.</strong> And in 1 instance out of 3, caveman actually made the model use <em>more</em> tokens than baseline.</p>

<p>This post is the receipts.</p>

<h2 id="setup">Setup</h2>

<p>Claude Code (<code class="language-plaintext highlighter-rouge">claude -p</code>) running Haiku 4.5, on <a href="https://github.com/scaleapi/SWE-bench_Pro-os">SWE-bench Pro Public</a>, ScaleAI’s hand-picked benchmark of real GitHub issues across multiple languages. I picked 101 instances ranked at difficulty 100–200 (the frontier: hard enough to stress the agent, easy enough that a resolve-rate delta is measurable).</p>

<p>Each task ran twice with the same user prompt. Once vanilla, once with the caveman system prompt appended via <code class="language-plaintext highlighter-rouge">--append-system-prompt</code>. Same model, same tools (Read/Edit/Write/Bash/Grep, with WebFetch/WebSearch off), same deterministic grader. Only the system prompt differs.</p>

<h2 id="headline-numbers">Headline numbers</h2>

<table>
  <thead>
    <tr>
      <th> </th>
      <th>baseline</th>
      <th>caveman</th>
      <th>Δ</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Resolve rate</td>
      <td><strong>93.5%</strong> (86/92)</td>
      <td><strong>90.2%</strong> (83/92)</td>
      <td>−3%</td>
    </tr>
    <tr>
      <td>Total cost</td>
      <td>$38.06</td>
      <td>$33.66</td>
      <td>−12%</td>
    </tr>
    <tr>
      <td>Avg cost/run</td>
      <td>$0.41</td>
      <td>$0.37</td>
      <td>−12%</td>
    </tr>
    <tr>
      <td>Avg output tokens/run</td>
      <td>15.3 k</td>
      <td>13.2 k</td>
      <td><strong>−14%</strong></td>
    </tr>
    <tr>
      <td>Avg turns/run</td>
      <td>42</td>
      <td>39</td>
      <td>−8%</td>
    </tr>
    <tr>
      <td>Avg duration/run</td>
      <td>5.2 min</td>
      <td>4.6 min</td>
      <td>−12%</td>
    </tr>
  </tbody>
</table>

<p>92 paired instances completed (9 hit dataset defects on the SWE-bench side and were dropped). Caveman is cheaper, faster, and slightly less reliable, but the resolve-rate gap is not statistically significant at this n.</p>

<h2 id="why-is-it-14-not-65">Why is it 14%, not 65%?</h2>

<p>Because in an agentic coding loop, the model doesn’t actually emit much prose.</p>

<p>I went through every session transcript and measured what fraction of the model’s output is narrative text vs. structured content (tool-call JSON, file paths, code, diffs):</p>

<ul>
  <li><strong>Baseline output: 13.3% prose, 86.7% structured (tool calls, file contents, code).</strong></li>
  <li><strong>Caveman output: 9.5% prose, 90.5% structured.</strong></li>
</ul>

<p>That number is the ceiling. <strong>Even if caveman compressed all prose to zero, the maximum possible savings on output tokens is ~13%.</strong> We measured 14%. Caveman is doing roughly the best it could possibly do given how much prose is even <em>available</em> to compress.</p>

<p>The 65% headline figure on caveman’s repo comes from natural-language chat tasks where prose is 90%+ of the output. In an agent loop, that’s flipped: the model is mostly generating Bash commands, Edit operations, and reading code. None of that can be cavemanned. <em>“chk file. edit fn. run test.”</em> is fine for prose; you can’t compress <code class="language-plaintext highlighter-rouge">Bash(command="CGO_ENABLED=0 go test ./models -run TestGetCveContentTypes -v 2&gt;&amp;1")</code>.</p>

<h2 id="what-caveman-speak-looks-like">What caveman-speak looks like</h2>

<p>Same task, same 13-line patch. Baseline opens:</p>

<blockquote>
  <p>“I’ll start by understanding the codebase structure and finding the failing tests to understand what needs to be implemented.”</p>
</blockquote>

<p>Caveman opens:</p>

<blockquote>
  <p>“Examining repo structure to understand CVSS handling and locate relevant files.”</p>
</blockquote>

<p>Baseline wrote 20 such narrative blocks on that task. Caveman wrote 2.</p>

<h2 id="the-case-where-caveman-doubled-the-tokens">The case where caveman <em>doubled</em> the tokens</h2>

<p>The mean (−14%) hides a wild distribution. Here’s the per-instance histogram of token savings, in 10% bins:</p>

<p><img src="/assets/images/caveman-token-histogram.png" alt="Histogram of per-instance output-token savings comparing caveman vs baseline. Green bars (right of zero) show instances where caveman used fewer tokens; red bars (left of zero) show instances where caveman used more. Distribution is roughly symmetric around zero with a slight right-skew." style="max-width: 700px; width: 100%; height: auto; display: block; margin: 20px auto;" /></p>

<p>Caveman saved tokens on 66% of instances. But it <em>increased</em> them on 34%, up to <strong>+102% on one instance</strong> (it literally doubled the output).</p>

<p>I dug into that doubling case (<code class="language-plaintext highlighter-rouge">vuls-73f0adad</code>, a Go vulnerability-scanner task). Both conditions resolved the task. But:</p>

<table>
  <thead>
    <tr>
      <th> </th>
      <th>baseline</th>
      <th>caveman</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Files patched</td>
      <td>1</td>
      <td>2</td>
    </tr>
    <tr>
      <td>Patch size</td>
      <td>+14 / −0</td>
      <td>+28 / −6</td>
    </tr>
    <tr>
      <td>Total tool calls</td>
      <td>24</td>
      <td><strong>69</strong></td>
    </tr>
    <tr>
      <td>Read calls</td>
      <td>6</td>
      <td>22</td>
    </tr>
    <tr>
      <td>Grep calls</td>
      <td>1</td>
      <td>11</td>
    </tr>
    <tr>
      <td>Sub-agent spawns</td>
      <td>0</td>
      <td>1</td>
    </tr>
  </tbody>
</table>

<p>Both started identically: read the test, read the source, grep for constants. Both edited the right file and made the test pass. Baseline stopped there. <strong>Caveman didn’t.</strong> It launched a 30-step exploration sweep through the rest of the codebase looking for callers of the function it just modified, spawned an Explore sub-agent, and edited a <em>second</em> file that didn’t actually need editing. The test passes without those changes.</p>

<p>So caveman’s compressed-output style didn’t make the model write less. It made the model do more <em>work</em>. Each tool call carries its own input/output token overhead. Saving 5 tokens per text block doesn’t help if you make 45 extra tool calls.</p>

<p>This isn’t unique to caveman. It’s a general pattern when you tell a model to be terse. The saved budget gets reinvested somewhere, often in additional exploration.</p>

<h2 id="same-problem-different-code">Same problem, different code</h2>

<p>Here’s the surprise nobody asked for. Of the 79 instances where both conditions resolved, only <strong>3 produced byte-identical patches</strong>. The other 76 reached different valid solutions:</p>

<ul>
  <li>61% of pairs touched the <strong>exact same set of files</strong>.</li>
  <li>But the actual lines they changed are mostly different. Typically only ~35% of changed lines appear in both patches.</li>
  <li>In 43% of pairs, less than 30% of the changed lines overlap: essentially different implementations of the same fix.</li>
</ul>

<p>In other words: the two configurations agreed on <em>where</em> the bug was, but wrote substantively different code to fix it. Caveman isn’t just writing a terser version of the baseline patch. The model takes a visibly different path and lands on a different valid fix.</p>

<p>This is partly a property of SWE-bench Pro (its grader admits many valid implementations per task), but it’s also a reminder: a prompt-style change isn’t surface-level. It rewires the trajectory.</p>

<h2 id="so-should-you-use-it">So should you use it?</h2>

<p><strong>At scale (automated agentic systems running thousands of jobs a day), turn it on.</strong> 12% lower cost is millions of dollars at any non-trivial volume. The quality risk is real but small (a ~3% resolve-rate gap that isn’t statistically significant on our data).</p>

<p><strong>As a single user, I wouldn’t bother.</strong> You trade a layer of visibility into the model’s reasoning (the prose is where you see <em>why</em> the model is doing what it’s doing) for savings that don’t move the needle on a personal API bill.</p>

<h2 id="caveats">Caveats</h2>

<ul>
  <li>Single model (Haiku 4.5). Larger models with more reasoning capacity might respond differently to the compression instruction.</li>
  <li>Single harness (Claude Code in headless mode). Other agent frameworks may show different ratios of prose to tool-args.</li>
  <li>The caveman system prompt itself adds ~69 lines of instructions and examples to caveman’s input.</li>
</ul>

<h2 id="the-real-lesson">The real lesson</h2>

<p>Tested in chat ≠ works in agent. When the bulk of your model’s output is structured (tool args, code, file contents), output-style tweaks can’t move the needle far. <strong>Always run a paired A/B on your actual workload before believing a prompt-engineering claim, especially a viral one.</strong></p>

<p>Caveman works. It was just oversold by the hype, for coding at least.</p>]]></content><author><name>Nathan Cavaglione</name></author><summary type="html"><![CDATA[65% token savings was the promise. The reality is 5x lower.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://ncvgl.github.io/assets/images/caveman-mosaic-thumb.png" /><media:content medium="image" url="https://ncvgl.github.io/assets/images/caveman-mosaic-thumb.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Murmur: Free Meeting Transcription</title><link href="https://ncvgl.github.io/posts/murmur/" rel="alternate" type="text/html" title="Murmur: Free Meeting Transcription" /><published>2026-04-12T00:00:00+00:00</published><updated>2026-04-12T00:00:00+00:00</updated><id>https://ncvgl.github.io/posts/murmur</id><content type="html" xml:base="https://ncvgl.github.io/posts/murmur/"><![CDATA[<p><img src="/assets/images/murmur.png" alt="Murmur transcribing a YouTube podcast in real-time" style="max-width: 100%; height: auto; display: block; margin: 20px 0;" /></p>

<p><strong>Try it:</strong> <a href="https://murmur.ncvgl.com">murmur.ncvgl.com</a>
<br /><strong>Star it:</strong> <a href="https://github.com/ncvgl/murmur">github.com/ncvgl/murmur</a></p>

<p>Meeting recorders charge $10–30 a month. Murmur is free. Forever.</p>

<p>No installation. No backend. No API costs. No data leaving your computer.</p>

<p>Just open <a href="https://murmur.ncvgl.com">murmur.ncvgl.com</a> and click Start. Works on Zoom, Meet, Teams — anything.</p>

<p><strong>How it works</strong></p>

<p><a href="https://github.com/moonshine-ai/moonshine">Moonshine v1</a>, a state-of-the-art speech model from ex-Googlers, runs locally in your browser. It listens to your mic and speakers, transcribes in real-time, and works without internet.</p>

<p><strong>Why it’s free</strong></p>

<p>Other tools cost money because they stream your audio to a server. Murmur has no server. The AI runs on your laptop, so the only cost is the electricity you were already paying for.</p>

<p><strong>The tradeoff</strong></p>

<p>~90% accuracy. English only. No speaker labels. But ChatGPT doesn’t need a perfect transcript to write an accurate meeting summary — it just needs the gist, and Murmur gives it that.</p>]]></content><author><name>Nathan Cavaglione</name></author><summary type="html"><![CDATA[No installation. No backend. No API.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://ncvgl.github.io/assets/images/murmur.png" /><media:content medium="image" url="https://ncvgl.github.io/assets/images/murmur.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">A Prompt Queue for Claude Code</title><link href="https://ncvgl.github.io/posts/claude-code-prompt-queue/" rel="alternate" type="text/html" title="A Prompt Queue for Claude Code" /><published>2026-04-10T00:00:00+00:00</published><updated>2026-04-10T00:00:00+00:00</updated><id>https://ncvgl.github.io/posts/claude-code-prompt-queue</id><content type="html" xml:base="https://ncvgl.github.io/posts/claude-code-prompt-queue/"><![CDATA[<p><img src="/assets/images/prompt-queue.jpeg" alt="Claude Code prompt queue plugin" style="max-width: 600px; width: 100%; height: auto; display: block; margin: 20px 0;" /></p>

<p><strong><a href="https://github.com/ncvgl/claude-prompt-queue">github.com/ncvgl/claude-prompt-queue</a></strong></p>

<p>Codex launched with task queues. Claude Code was missing one. Not anymore.</p>

<p>You give it a task. It finishes. Then stops. No queue. No batching. Just waiting for you.</p>

<p>You can’t walk away. You have to sit there feeding it prompts like in 2023.</p>

<p>It’s also one of the most requested features on their GitHub.</p>

<p>So I added it with a plugin. 30 lines of bash. Using stop hooks.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>next: refactor the auth module
next: write tests for it
next: just keep going, resolve any question by yourself
</code></pre></div></div>

<p>Queue 10 tasks. Walk away. Come back to finished work.</p>

<p>Install with:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/plugin marketplace add ncvgl/claude-prompt-queue
/plugin install prompt-queue@prompt-queue-marketplace
</code></pre></div></div>

<p><strong>FAQ</strong>: Yes, Claude has an implicit CreateTask tool but it can stop in the middle of a task asking a question that you are not there to answer. This plugin forces Claude to continue.</p>]]></content><author><name>Nathan Cavaglione</name></author><summary type="html"><![CDATA[30 lines of bash so you can walk away]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://ncvgl.github.io/assets/images/prompt-queue.jpeg" /><media:content medium="image" url="https://ncvgl.github.io/assets/images/prompt-queue.jpeg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Cloning Slack with Claude Code</title><link href="https://ncvgl.github.io/posts/slawk/" rel="alternate" type="text/html" title="Cloning Slack with Claude Code" /><published>2026-03-02T00:00:00+00:00</published><updated>2026-03-02T00:00:00+00:00</updated><id>https://ncvgl.github.io/posts/slawk</id><content type="html" xml:base="https://ncvgl.github.io/posts/slawk/"><![CDATA[<p><img src="/assets/images/slawk.png" alt="Slawk - a Slack clone built with AI agents" style="max-width: 600px; width: 100%; height: auto; display: block; margin: 20px 0;" /></p>

<p><strong><a href="https://github.com/ncvgl/slawk">github.com/ncvgl/slawk</a></strong></p>

<p>I posted about building a Slack clone using multiple AI agents. Everybody asked: “How did the agents talk to each other?”</p>

<p>I initially treated Claude Code like a smart assistant — write prompt, get code, review, repeat. But after 30 exchanges, context bloat kicked in: slower responses, confusing outputs, compaction takes a few minutes…</p>

<p>So I tried something different: What if I treated AI like a dev team instead of a chatbot?</p>

<p><strong>One persistent “CTO” session</strong> that plans, delegates, and reviews. It never writes code. It just thinks.</p>

<p><strong>Ephemeral “developer” sessions</strong> that get spawned for single tasks, build the feature, commit, and get deleted. No conversation history. No memory of previous tasks.</p>

<p><strong>Disposable “QA” sessions</strong> that test the app like a human user, report bugs, and disappear.</p>

<p><img src="/assets/images/slawk-flow.svg" alt="Agent orchestration flow diagram" style="max-width: 520px; width: 100%; height: auto; display: block; margin: 20px 0;" /></p>

<p>QA sessions use ~10-20 tool calls, developer sessions average 30-50K tokens per feature, the CTO session sits around 80K after 3 days. Total: maybe $20-30. The velocity gains are worth 100x that.</p>

<p>How much the CTO controls the handoff depends on how much you trust the system. Early on I had it write each developer prompt to a local <code class="language-plaintext highlighter-rouge">.md</code> file — I’d review it, then manually start the subagent session. Once I stopped changing anything, I let the CTO spawn subagents <a href="https://code.claude.com/docs/en/agent-teams">directly</a>. Same outcome with less friction.</p>

<p>Here’s the prompt I gave the CTO for a real task:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Implement thread replies as the next feature.
Use TDD: write Playwright test first, then implement.
The feature should work end-to-end (backend + frontend).
Commit when done and report back.
</code></pre></div></div>

<p>That’s it. The CTO plans the task then spawns a developer agent with this prompt:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>You are implementing thread replies for a Slack clone.

Backend requirements:
- Add thread_id foreign key to messages table
- Add GET /api/messages/:id/replies endpoint
- Add real-time events for new replies

Frontend requirements:
- Add "Reply in thread" button to messages
- Add right sidebar that shows thread when opened
- Show reply count on parent message
- Real-time updates when new replies arrive

Process:
1. Write Playwright test that verifies the full flow
2. Implement backend changes
3. Implement frontend changes
4. Iterate until test passes
5. Run ALL existing tests to ensure nothing broke
6. Commit with message: "feat: Add thread replies"
</code></pre></div></div>

<p>The agent has no context about previous features, so it explores the codebase first:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">grep</span> <span class="nt">-r</span> <span class="s2">"messages"</span> backend/src <span class="nt">--include</span><span class="o">=</span><span class="s2">"*.ts"</span>
<span class="nb">cat </span>backend/src/routes/messages.ts
<span class="nb">cat </span>frontend/src/components/MessageList.tsx
</code></pre></div></div>

<p>5-6% of its context window. It finds what it needs and gets to work.</p>

<p><strong>Fresh eyes catch mistakes.</strong> Without context, the agent can’t make assumptions. It reads the actual code, which often reveals inconsistencies a loaded agent would miss.</p>

<p><strong>TDD is the safety net.</strong> If the agent misses something, the test fails. It iterates:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Test failed: Thread sidebar doesn't open when clicking reply count

Debugging... found the issue: missing event listener on reply count button
Fixed and re-running tests...

All tests passing ✅
</code></pre></div></div>

<p><img src="/assets/images/slawk-tdd.png" alt="Developer agent running Playwright tests, iterating until all pass" style="max-width: 100%; height: auto; display: block; margin: 20px 0;" /></p>

<p><strong>Speed and parallelization.</strong> A fresh agent responds in 5 seconds vs 15-20 for a bloated one. And since agents don’t share context, they can work simultaneously using <a href="https://code.claude.com/docs/en/common-workflows#subagent-worktrees">git worktrees</a>.</p>

<p>After building 4-5 features, I tell the CTO:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Spawn a QA agent to test the app using the MCP browser extension.
Have it test the main features and report bugs it finds.
</code></pre></div></div>

<p>The CTO spawns a QA agent with this brief below. 
Make sure you have it enabled by typing <code class="language-plaintext highlighter-rouge">/chrome</code> in Claude Code. See this <a href="https://code.claude.com/docs/en/chrome">chrome extension</a></p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>You are a QA engineer testing a Slack clone.

Open the app at http://localhost:5173 using Chrome MCP.
Test these features like a real user:
- Register a new account
- Create a channel
- Send messages
- Try replying in a thread
- Upload a file
- Use search

For each bug:
- Take a screenshot
- Note the steps to reproduce
- Rate severity (Critical/High/Medium/Low)

Write your findings to qa-report.md
</code></pre></div></div>

<p>To validate UI accuracy, I gave it two URLs: my local app and an actual Slack workspace I’m part of. Its job was to test the same features in both and flag differences. It clicks buttons, fills forms, pulls JavaScript from the page for advanced debugging, takes screenshots when things break.</p>

<p><img src="/assets/images/slawk-qa-reaction.png" alt="QA agent navigating the reaction feature and confirming the thumbs up works" style="max-width: 100%; height: auto; display: block; margin: 20px 0;" /></p>

<p><img src="/assets/images/slawk-qa-browser.png" alt="The result in Slawk — thumbs up reaction on a message" style="max-width: 100%; height: auto; display: block; margin: 20px 0;" /></p>

<p>Something I didn’t ask for: halfway through, it created a <a href="https://github.com/ncvgl/slawk/blob/main/frontend/design-reference/slack-design-system.md">slack-design-system.md</a> file — colors, spacing, component patterns, all mapped from the real Slack UI. It just decided having a design anchor would help it stay consistent. I thought that was smart.</p>

<p>After 10-15 minutes, I get a markdown file:</p>

<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gh"># QA Report - Thread Feature Testing</span>

<span class="gu">## Bug #1: Thread sidebar doesn't show typing indicators</span>
Severity: Medium
Steps: Open thread, have another user type a reply
Expected: See "User is typing..." in thread
Actual: No typing indicator appears

<span class="gu">## Bug #2: Thread reply count doesn't update in real-time</span>
Severity: High
Steps: User A opens channel, User B replies in thread
Expected: Reply count updates immediately
Actual: Need to refresh to see new count
</code></pre></div></div>

<p><img src="/assets/images/slawk-qa-checklist.png" alt="QA agent feature checklist — 15+ features tested, all marked PASS" style="max-width: 100%; height: auto; display: block; margin: 20px 0;" /></p>

<p>The CTO reads this report and spawns fix agents for each bug. Just ask it for subagents and you will see it spawn them.</p>

<p><strong>The last 20% takes 80% of the time.</strong> After the QA agent found 14 bugs, I asked the CTO to fix them all in parallel. It ran them 3 at a time using subagents. Three hours total.</p>

<p>Half that time went to a single bug: removing a star icon stuck in the bottom-right corner of the screen. The agent tried everything — searched the codebase, modified CSS, rebuilt components. Nothing worked. Because the icon wasn’t part of Slawk. It was the Claude MCP extension overlaid on top of the browser.</p>

<p>The agent had no way to know that. It needed me to step in and say: skip this one, it’s not an issue.</p>

<p><img src="/assets/images/slawk-bugs.png" alt="14 bugs tracked in a table — the last row reads 'Not a bug, it's Claude Code itself'" style="max-width: 100%; height: auto; display: block; margin: 20px 0;" /></p>

<p>That’s the pattern. Parallel AI work is fast until it hits something it can’t resolve alone — and then it waits for you. The moment you step in, 10 agents working simultaneously collapse to one, because your attention can only be in one place. <strong>You are the bottleneck.</strong></p>

<p>The key to speed isn’t better prompts. It’s removing yourself from the feedback loop. And occasionally checking if it needs you to step back in.</p>]]></content><author><name>Nathan Cavaglione</name></author><summary type="html"><![CDATA[Coding is now AI Agent Management]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://ncvgl.github.io/assets/images/slawk.png" /><media:content medium="image" url="https://ncvgl.github.io/assets/images/slawk.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">PolyGPT</title><link href="https://ncvgl.github.io/posts/polygpt/" rel="alternate" type="text/html" title="PolyGPT" /><published>2025-11-16T00:00:00+00:00</published><updated>2025-11-16T00:00:00+00:00</updated><id>https://ncvgl.github.io/posts/polygpt</id><content type="html" xml:base="https://ncvgl.github.io/posts/polygpt/"><![CDATA[<script>
  window.location.href = "https://polygpt.app";
</script>

<noscript>
  <meta http-equiv="refresh" content="0; url=https://polygpt.app" />
</noscript>

<p>Redirecting to <a href="https://polygpt.app">PolyGPT</a>...</p>]]></content><author><name>Nathan Cavaglione</name></author><summary type="html"><![CDATA[Stop tab-switching between AI tools]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://ncvgl.github.io/assets/images/polygpt-logo.png" /><media:content medium="image" url="https://ncvgl.github.io/assets/images/polygpt-logo.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Manga2Anime</title><link href="https://ncvgl.github.io/posts/manga2anime/" rel="alternate" type="text/html" title="Manga2Anime" /><published>2025-10-28T00:00:00+00:00</published><updated>2025-10-28T00:00:00+00:00</updated><id>https://ncvgl.github.io/posts/manga2anime</id><content type="html" xml:base="https://ncvgl.github.io/posts/manga2anime/"><![CDATA[<p><img src="/assets/images/hxh.webp" alt="Hunter x Hunter manga panels transformed to anime" style="max-width: 600px; width: 100%; height: auto; display: block; margin: 20px 0;" /></p>

<h2 id="from-static-panels-to-moving-animation">From Static Panels to Moving Animation</h2>

<p>I got a little addicted to turning my favorite mangas into animated versions using Google’s Nano Banana, Imagen3 and Veo3.1 models. What started as an experiment became a week-long exploration of what’s possible (and what’s not) with current AI video generation. Below is my best creation.</p>

<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden; max-width: 100%; margin: 20px 0;">
  <iframe style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;" src="https://www.youtube.com/embed/cDc-BdmJZK8" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="">
  </iframe>
</div>

<h2 id="the-reality-check">The Reality Check</h2>

<p>After spending a day working with Veo 3.1 to turn half a chapter into an animated version, I had to walk back on my initial excitement: <strong>we’re still not there yet</strong> on full automatic manga-to-anime generation.</p>

<p>Video and image models are mind-blowing, but turning static manga into moving anime is a different beast. The main limitation is that the model has to invent too much. It can’t take a style reference for how the anime should look yet, so it fills in the blanks and drifts too far from the intended style. The results are good enough for fan-made action, but not studio quality.</p>

<p>Another limitation is keeping voice and character consistency across scenes, with currently no feature for those except prompting.</p>

<h2 id="the-recipe">The Recipe</h2>

<p>That said, I found a few cheap tricks that make the difference. The key idea is to have very neat “base images” to generate the videos from:</p>

<ol>
  <li><strong>Crop the image</strong> from the manga with a screenshot tool</li>
  <li><strong>Remove any undesirable elements</strong> using Imagen3 (paint the areas you want removed, like text bubbles)</li>
  <li><strong>Color the image</strong> using Gemini Nano Banana (tell it “Color EVERYTHING in this image” otherwise it gets lazy)</li>
  <li><strong>Extend the image</strong> with Imagen3 to fit a 16:9 format (that’s what Veo 3.1 expects)</li>
  <li><strong>Animate it</strong> using Veo3.1 and mention the text bubbles so they are generated in the audio</li>
  <li><strong>Stick all the videos together</strong> using gemini-cli, with a low volume soundtrack to convey emotions</li>
</ol>

<p>It’s not anything that can be easily automated with code. A lot of redoing with custom prompting is involved, but it can accelerate the work of artists.</p>

<p>Here is a video breaking down the process visually:</p>

<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden; max-width: 100%; margin: 20px 0;">
  <iframe style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;" src="https://drive.google.com/file/d/1vcRVT0qS76wk691K-Df1zaH9PcJ37gpz/preview" frameborder="0" allow="autoplay" allowfullscreen="">
  </iframe>
</div>

<h2 id="the-verdict">The Verdict</h2>

<p>AI is evolving fast, but full studio automation is still a few steps away.</p>]]></content><author><name>Nathan Cavaglione</name></author><summary type="html"><![CDATA[Bringing black & white pages to life with Google's AI models]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://ncvgl.github.io/assets/images/hxh.webp" /><media:content medium="image" url="https://ncvgl.github.io/assets/images/hxh.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">GitMermaid</title><link href="https://ncvgl.github.io/posts/gitmermaid-architecture-diagrams/" rel="alternate" type="text/html" title="GitMermaid" /><published>2025-09-28T00:00:00+00:00</published><updated>2025-09-28T00:00:00+00:00</updated><id>https://ncvgl.github.io/posts/gitmermaid-architecture-diagrams</id><content type="html" xml:base="https://ncvgl.github.io/posts/gitmermaid-architecture-diagrams/"><![CDATA[<p>This post redirects to GitMermaid - a tool that automatically generates architecture diagrams from your Git repositories.</p>]]></content><author><name>Nathan Cavaglione</name></author><summary type="html"><![CDATA[AI-generated mermaid architecture diagrams from any GitHub repo]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://ncvgl.github.io/assets/images/ui_screenshot.png" /><media:content medium="image" url="https://ncvgl.github.io/assets/images/ui_screenshot.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Retrofitting Legacy Forms</title><link href="https://ncvgl.github.io/posts/retrofitting-legacy-forms/" rel="alternate" type="text/html" title="Retrofitting Legacy Forms" /><published>2025-08-17T00:00:00+00:00</published><updated>2025-08-17T00:00:00+00:00</updated><id>https://ncvgl.github.io/posts/retrofitting-legacy-forms</id><content type="html" xml:base="https://ncvgl.github.io/posts/retrofitting-legacy-forms/"><![CDATA[<p><img src="/assets/images/fill-my-paperwork.png" alt="Legacy Forms" style="max-width: 400px; width: 100%; height: auto; display: block; margin: 20px auto;" /></p>

<p>The webapp is <a href="https://fill-my-papers-424605661533.europe-west9.run.app/">here</a>. <br />
The code is <a href="https://github.com/ncvgl/fill-my-paperwork">here</a>.</p>

<p>… So the other day, I had to fill another government form by paper. Take a photo. Send it back. The usual.</p>

<p>Let’s say I’d had enough of this workflow. Government sends you a PDF, you print it, fill it by hand, scan it, email it back. Or you try some digital tools you have to pay for.</p>

<p>So I got bored of the repetitive work and built a service to fix this. Upload your form, it detects the fields, fills them with fake data, you correct what needs correcting, download, send.</p>

<p>Basically retrofitting legacy forms that organisations could not bother to put into a proper website. Not that I blame them - building web forms is work. PDF Forms are easy to switch and update.</p>

<p>It is a simple side project that helps with daily admin tasks. Taxes, subscriptions, utilities - all those forms that live in the stone age of user experience.</p>

<p>For now it’s fake data only, but I’m considering an extension where you store your actual info and it auto-fills everything.</p>

<p>Every time I use this, I’m reminded that good UX isn’t about flashy animations or trendy frameworks. It’s about removing the gap between what you want to do and actually doing it.</p>

<p>Government forms are the perfect example of that gap. They want your information. You want to give it to them. But somehow we’ve created this elaborate ritual involving printers, scanners, and PDF readers from 2003.</p>

<p>Sometimes the best innovation is just… making things work.</p>

<p>The service is free, no login, no storage, open-source.</p>

<p><img src="/assets/images/demo-fill-paperwork.png" alt="Legacy Forms" style="max-width: 800px; width: 100%; height: auto; display: block; margin: 20px auto;" /></p>

<p><br /></p>

<p><img src="https://raw.githubusercontent.com/ncvgl/fill-my-paperwork/main/demo.gif" alt="Legacy Forms" style="max-width: 800px; width: 100%; height: auto; display: block; margin: 20px auto;" /></p>]]></content><author><name>Nathan Cavaglione</name></author><summary type="html"><![CDATA[Because governments still love their PDFs]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://ncvgl.github.io/assets/images/fill-my-paperwork.png" /><media:content medium="image" url="https://ncvgl.github.io/assets/images/fill-my-paperwork.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Why you can’t just copy NVIDIA’s GPUs</title><link href="https://ncvgl.github.io/posts/nvidia-gpu/" rel="alternate" type="text/html" title="Why you can’t just copy NVIDIA’s GPUs" /><published>2025-08-11T00:00:00+00:00</published><updated>2025-08-11T00:00:00+00:00</updated><id>https://ncvgl.github.io/posts/nvidia-gpu</id><content type="html" xml:base="https://ncvgl.github.io/posts/nvidia-gpu/"><![CDATA[<p><img src="/assets/images/nvidia.webp" style="max-width: 400px; width: 100%; height: auto; display: block; margin: 20px 0;" /></p>

<p>You can copy a chip; you can’t copy the city around it. That, more than clock speeds or clever slides, is why NVIDIA - now valued in the 4.4 trillions - keeps its lead. The firm did not just build silicon; it laid roads, wrote the road signs, and taught everyone to drive on them.</p>

<p>Start with the language of the place. For two decades developers have learned to think in CUDA. The popular tools - PyTorch and TensorFlow - lean on it by default. Under the bonnet sit libraries with unsexy names (cuDNN for neural nets, cuBLAS for linear algebra, NCCL for multi-GPU teamwork) that most teams never see but always use. Higher up, deployment tools - TensorRT and Triton - turn models into production workhorses. Try to lift all that code to another brand of chip and you hit the small print: NVIDIA’s CUDA licence forbids translation layers that pretend to be CUDA elsewhere (the ZLUDA saga is the cautionary tale). Like it or not, the city speaks one language.</p>

<p>Then there is the box itself. NVIDIA does not sell loose parts so much as finished appliances. DGX servers and NVL72 racks, built around Grace + GPU “superchips” (GH200 today, GB200/Blackwell tomorrow), are wired with NVLink and NVSwitch so that eight, sixteen or seventy-two GPUs behave like one big one. Imagine seventy-two chefs making one soup. If they shout across a corridor (plain PCIe and ordinary Ethernet), half the day is spent coordinating. Give them a quiet kitchen - fast, private communication - and dinner is ready sooner. Buyers do not pay for theoretical flops; they pay to finish on Tuesday rather than Friday.</p>

<p>Owning the plumbing turned out to be strategy, not housekeeping. When NVIDIA bought Mellanox, it acquired the city’s transit system: InfiniBand for low-latency links, an AI-tuned flavour of Ethernet called Spectrum-X, and programmable adapters known as BlueField DPUs (with a software kit called DOCA). With the roads in hand, the company can co-design cars and traffic lights. That is hard to rent by the hour.</p>

<p>All of this still needs a place to be built. At the frontier, that place is Taiwan. NVIDIA’s top chips are fabricated at TSMC on custom processes (4N/4NP) and assembled with advanced packaging called CoWoS, which stitches huge dies to stacks of very fast memory. The memory - HBM3E - comes from SK Hynix, Micron and Samsung, but not on a whim: parts must be qualified, and capacity is reserved years ahead. The limiting factor in this boom has often been CoWoS slots and HBM allocation, not bravado. Without those golden tickets, an “H100-killer” remains a handsome rendering.</p>

<p>Who, then, looks capable of building a rival metropolis ? Startup Graphcore tried. A brilliant architecture that struggled to win ecosystem &amp; customers at scale, it was ultimately sold to SoftBank in 2024.
And on the grown-ups side ? We have some cloud landlords and a few chip specialists. Google’s TPUs are tightly woven into its own software mill; AWS pushes Trainium and Inferentia (now Trainium 2) to control cost across a global fleet; Microsoft’s Maia and Cobalt are co-designed with frontier models in mind; Meta’s MTIA leans on the gravity of PyTorch. Among chipmakers, AMD’s MI300/MI325X/MI350 paired with ROCm is the closest on raw silicon and is steadily improving the software; Intel’s Gaudi 3 offers sharp price-per-job in some training and inference, especially for Ethernet-centric shops. Inside China, Huawei’s Ascend 910B/910C rides a home-grown software stack called CANN, a deliberate CUDA alternative for a parallel ecosystem.</p>

<p>Beating NVIDIA, then, is not a single trick but a city plan. You need a developer path that feels native in PyTorch and TensorFlow rather than “ported”. You need racks that scale as one machine, not a suggestion to “use more Ethernet”. You need control over the network - InfiniBand-class links or an AI-tuned Ethernet like Spectrum-X, ideally with offload smarts in the BlueField mould. You need manufacturing booked, not promised: CoWoS capacity at TSMC and HBM3E from the big three, with qualification signed off. And if your migration story is “we’ll just run CUDA elsewhere”, you will have to explain how you navigate the licence.</p>

<p>None of this says NVIDIA is immortal. Cities ossify; fashions change. A rival that offers a familiar software path, rack-scale smoothness, owned plumbing and a guaranteed Taiwanese supply chain could yet siphon tenants. Until then, the premium is not only hype. It is the rent you pay for a place where the streets are paved, the buses run on time and the favourite coffee cart knows your order.</p>]]></content><author><name>Nathan Cavaglione</name></author><summary type="html"><![CDATA[Better wake up early]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://ncvgl.github.io/assets/images/nvidia.webp" /><media:content medium="image" url="https://ncvgl.github.io/assets/images/nvidia.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">The Dead Neuron</title><link href="https://ncvgl.github.io/posts/the-dead-neuron/" rel="alternate" type="text/html" title="The Dead Neuron" /><published>2025-08-08T00:00:00+00:00</published><updated>2025-08-08T00:00:00+00:00</updated><id>https://ncvgl.github.io/posts/the-dead-neuron</id><content type="html" xml:base="https://ncvgl.github.io/posts/the-dead-neuron/"><![CDATA[<p><img src="/assets/images/dead-neuron.png" alt="Dead Neuron" style="max-width: 400px; width: 100%; height: auto; display: block; margin: 20px 0;" /></p>

<p>Since working at Google, I’ve come to see big corporations like a human brain. Complex, adaptive, full of redundant paths.</p>

<p>If one neuron goes silent, the signal finds a way around. It always does. You know the person I’m talking about. The one who’s supposed to own some piece of work, but hardly replies. 
You try to loop them in, move a piece forward — but nothing. Just radio silence.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>That’s what I call the dead neuron.
</code></pre></div></div>

<p>In a startup, that’d be a blocker. In a big corp ? Not really. People route around. They find a workaround. The task moves, the project progresses, just without them.</p>

<p>And here’s the thing: dead neurons train people to stop depending on them. To skip them. To forget them. They become a name you avoid mentioning. A calendar invite you don’t bother sending. Not because you’re mad - but because you’ve adapted.
Some folks even lean into it. “If I stop replying, they’ll stop asking.” And sure, they do.</p>

<p>So if someone sent you this, maybe they tried to ping you — and the signal died in your synapse.</p>

<p><code class="language-plaintext highlighter-rouge">Reconnect.</code></p>

<hr />

<h3 id="post-scriptum">Post scriptum</h3>

<p>The opposite is just as real. If you always reply - even to things you don’t own - just to help out, you slowly become the default active neuron for that signal.</p>

<p>In big corps, work is just a chain of neuron activations: one ping lighting up another. 
And if someone manages to pass a task to you once, they’ll come back. That’s how you become the go-to, the shortcut.</p>

<p>My manager used to say, <em>“Nathan, be careful - because the reward for good work is always more work”</em>.</p>

<p>So yeah, don’t be a dead neuron. But also set your boundaries. Or you’ll get wired into flows you never meant to be part of.</p>]]></content><author><name>Nathan Cavaglione</name></author><summary type="html"><![CDATA[This guy whose strategy is to stop answering]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://ncvgl.github.io/assets/images/dead-neuron.png" /><media:content medium="image" url="https://ncvgl.github.io/assets/images/dead-neuron.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>