<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nate Voss</title>
    <description>The latest articles on DEV Community by Nate Voss (@natevoss).</description>
    <link>https://dev.to/natevoss</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3839442%2F8d858ab2-90a7-47dd-b9ee-fa8c73b19227.png</url>
      <title>DEV Community: Nate Voss</title>
      <link>https://dev.to/natevoss</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/natevoss"/>
    <language>en</language>
    <item>
      <title>The Leverage Shift: Why Infrastructure Cost Doesn't Matter Anymore</title>
      <dc:creator>Nate Voss</dc:creator>
      <pubDate>Fri, 08 May 2026 07:15:44 +0000</pubDate>
      <link>https://dev.to/natevoss/the-leverage-shift-why-infrastructure-cost-doesnt-matter-anymore-3o1m</link>
      <guid>https://dev.to/natevoss/the-leverage-shift-why-infrastructure-cost-doesnt-matter-anymore-3o1m</guid>
      <description>&lt;p&gt;Last month I built a feature that would've consumed my monthly API budget three years ago. It involved processing 50,000 tokens of context, running chains of prompts, error recovery, retries. I spent maybe four dollars. Not 400. Not "significant." Four.&lt;/p&gt;

&lt;p&gt;That casually happened during a normal Tuesday build. I wasn't optimizing for cost. I wasn't watching the meter. I was shipping clarity. Breaking down a complex decision into smaller, dumber steps. And the economics of doing that were so cheap that they didn't show up on my radar anymore.&lt;/p&gt;

&lt;p&gt;This is the quiet shift nobody talks about when they talk about AI. It's not "AI is now viable for startups". Everyone's saying that, and they're right. It's deeper: the economic game of building and shipping software has fundamentally changed shape, and most people are still playing chess with the old board.&lt;/p&gt;

&lt;h2&gt;
  
  
  The numbers
&lt;/h2&gt;

&lt;p&gt;Claude 3.5 Sonnet costs $3 per million input tokens, $15 per million output tokens. GPT-4o is $5/$15. A context window that can hold a small novel costs pennies to run inference on.&lt;/p&gt;

&lt;p&gt;A solo developer building a feature that makes 10,000 API calls per day runs maybe $150/month. That's the cost of a coffee subscription. Compare that to the cost of hiring one mid-level engineer to ship the same thing, or the infrastructure capital you needed in 2015 to run equivalent workloads yourself. Tens of thousands in hardware, plus the engineering time to maintain it.&lt;/p&gt;

&lt;p&gt;But the real shift isn't in the absolute cost. It's in &lt;em&gt;who gets to ship&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The moat problem
&lt;/h2&gt;

&lt;p&gt;Every "AI-first startup" shipping right now is built on this exact cost collapse. Someone got VC funding, hired a team, built something that calls Claude, made it prettier with a design system, and shipped it. The business model is usually "we mark up the API calls." Which means. And I'm not being harsh. They're playing with a moat they don't own.&lt;/p&gt;

&lt;p&gt;Your moat isn't the model. It isn't the tokens. It isn't the prompt. It's something else, or it doesn't exist.&lt;/p&gt;

&lt;p&gt;I've noticed this building systems that rely on language models. The feature that matters isn't "we call Claude to generate content." That's technical infrastructure anyone can replicate in an afternoon. The feature that matters is the specific way the system engages across platforms, the calibration of how much to reply versus broadcast, the calendar that knows when to rest. That only works because someone cares enough to refine it for 18 months and measure what actually lands with an audience. The API calls are the easy part.&lt;/p&gt;

&lt;p&gt;You can build that infrastructure for four dollars a month. You cannot buy the other layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open source vs the API
&lt;/h2&gt;

&lt;p&gt;This is where the calculation gets interesting. Self-hosting Llama 2 on a p3.8xlarge costs roughly $12/hour. For a low-volume feature (maybe 1,000 tokens/day), that's economically indefensible. You're paying for idle compute. For high-volume (millions of tokens/month), it pencils out.&lt;/p&gt;

&lt;p&gt;But "pencils out" ignores the hidden costs: maintenance, inference optimization, managing VRAM, handling failures, updating models. And it ignores the opportunity cost: that's your engineering time, not shipping the actual feature.&lt;/p&gt;

&lt;p&gt;The shift is that the crossover point has moved. Five years ago, building anything non-trivial in production meant: evaluate open-source models, find one that works, self-host it, hire someone to maintain it. The API was expensive; the infrastructure was cheap (because you didn't pay for idle time).&lt;/p&gt;

&lt;p&gt;Now the API is cheap enough that most solo projects shouldn't self-host. You're not choosing between "pay the API vendor" and "own our infrastructure." You're choosing between "pay $200/month" and "pay $50,000 in engineering for something that breaks in production and costs $3,000/month to run."&lt;/p&gt;

&lt;p&gt;There are exceptions. If you're running language models at hyperscaler volume (billions of tokens/month), self-hosting with cheaper open models becomes non-negotiable. But that's not the constraint on most projects. And even then, you're still paying for compute. You're just deciding to own the infrastructure instead of outsourcing the billing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real cost: clarity
&lt;/h2&gt;

&lt;p&gt;Here's what I didn't expect: cheaper infrastructure doesn't make the problems simpler. It moves them.&lt;/p&gt;

&lt;p&gt;The cost of building with AI used to be economic: can I afford to make this call? Now it's cognitive. Can I write the logic clearly enough that the model does what I actually need? Can I debug why this worked yesterday and not today? Can I handle the failure case when the model hallucinates?&lt;/p&gt;

&lt;p&gt;I spent a week recently on a single decision-making routine. The model was generating great output but missing the signal I needed buried in the analysis. I kept adding context, more examples, longer explanations. Finally hit a token budget and had to cut 70% of what I'd written. The version that worked. The one that was clear instead of thorough. Was the one I'd almost deleted.&lt;/p&gt;

&lt;p&gt;The use has moved from "can you afford compute?" to "can you think clearly?" And that's actually a more interesting gate.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means for solo builders
&lt;/h2&gt;

&lt;p&gt;You can now build the infrastructure of a Series A company, alone, for the cost of a Spotify subscription. That's real. Not metaphorically. Literally. The cloud bills are negligible. The engineering is finite.&lt;/p&gt;

&lt;p&gt;What you can't do is own a moat you didn't build. You can't ship a wrapper and expect market gravity to solve the rest. The people winning with AI right now aren't winning because they found a good model. They're winning because they found a real problem and got ruthlessly specific about solving it.&lt;/p&gt;

&lt;p&gt;The gate isn't capital anymore. The gate is clarity. Do you know what you're building? Do you know it better than anyone else? Can you measure whether it's working? Can you refine it based on signal instead of hope?&lt;/p&gt;

&lt;p&gt;That's the use. Infrastructure cost collapsing just made it possible to do alone.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>discuss</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Folks, need some feedback on this: https://dev.to/natevoss/i-wrote-a-rule-after-claude-got-is-x-built-wrong-4-times-looking-for-failure-modes-2f3i</title>
      <dc:creator>Nate Voss</dc:creator>
      <pubDate>Thu, 07 May 2026 10:24:08 +0000</pubDate>
      <link>https://dev.to/natevoss/folks-need-some-feedback-on-this-3g0c</link>
      <guid>https://dev.to/natevoss/folks-need-some-feedback-on-this-3g0c</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/natevoss/i-wrote-a-rule-after-claude-got-is-x-built-wrong-4-times-looking-for-failure-modes-2f3i" class="crayons-story__hidden-navigation-link"&gt;I wrote a rule after Claude got "is X built?" wrong 4 times. Looking for failure modes.&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/natevoss" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3839442%2F8d858ab2-90a7-47dd-b9ee-fa8c73b19227.png" alt="natevoss profile" class="crayons-avatar__image" width="96" height="96"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/natevoss" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Nate Voss
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Nate Voss
                
              
              &lt;div id="story-author-preview-content-3620934" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/natevoss" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3839442%2F8d858ab2-90a7-47dd-b9ee-fa8c73b19227.png" class="crayons-avatar__image" alt="" width="96" height="96"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Nate Voss&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/natevoss/i-wrote-a-rule-after-claude-got-is-x-built-wrong-4-times-looking-for-failure-modes-2f3i" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;May 6&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/natevoss/i-wrote-a-rule-after-claude-got-is-x-built-wrong-4-times-looking-for-failure-modes-2f3i" id="article-link-3620934"&gt;
          I wrote a rule after Claude got "is X built?" wrong 4 times. Looking for failure modes.
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/llm"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;llm&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/claude"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;claude&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/natevoss/i-wrote-a-rule-after-claude-got-is-x-built-wrong-4-times-looking-for-failure-modes-2f3i#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>I wrote a rule after Claude got "is X built?" wrong 4 times. Looking for failure modes.</title>
      <dc:creator>Nate Voss</dc:creator>
      <pubDate>Wed, 06 May 2026 12:03:25 +0000</pubDate>
      <link>https://dev.to/natevoss/i-wrote-a-rule-after-claude-got-is-x-built-wrong-4-times-looking-for-failure-modes-2f3i</link>
      <guid>https://dev.to/natevoss/i-wrote-a-rule-after-claude-got-is-x-built-wrong-4-times-looking-for-failure-modes-2f3i</guid>
      <description>&lt;p&gt;I wrote a rule for AI coding agents two days ago. It is untested in production sessions. I am posting it here to find its failure modes faster than I would by waiting for my own future mistakes to surface them.&lt;/p&gt;

&lt;p&gt;The rule is below first. Story and reasoning after.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Pre-Build Existence Audit Rule (v1, structural verification)

Status: Untested in production sessions. Test on a new project for 2-3 weeks
before considering global rollout.

Before claiming "feature X is not built / not implemented / missing":

1. Map
   rg -li "&amp;lt;keyword&amp;gt;" .                            # project repo
   rg -li "&amp;lt;keyword&amp;gt;" ~/.claude/projects/*/memory/ # agent memory
   If either &amp;gt;5 files match, use the file list to scope which to read.

2. Structural footprint scan (NOT just synonyms)
   Identify architectural invariants this feature class would require:
   - Integration/API → router definitions, endpoint registrations,
     plugin tool lists
   - Data → schema files, migrations, type definitions, persisted-entity fields
   - Background → cron entries, queue handlers, scheduled job registrations
   - Cross-service → service registry, infra config, IPC handlers
   - Memory/decisions → project_*.md files documenting prior shipment

   Stack discipline: footprints must be stack-appropriate. If unsure which
   architectural pattern applies, list 2-3 plausible alternatives
   (REST/GraphQL/RPC; cron/queue/webhook) and search each. Wrong-ontology
   audits feel rigorous but miss truth.

   Grep each invariant. If ANY return matches, "not built" is contradicted
   until you've read those matches.

3. Epistemic categorization. Label each match as ONE of:
   - Direct Proof: read the exact logic for the dimension being asked
   - Infrastructure Hint: schema/hooks/types only, not the specific logic
   - Partial Implementation: some footprints present, others missing
   - Global Absence: searched ALL relevant invariants across ENTIRE repo,
     found no footprint

4. Cite without fabricating
   Quote 3-5 lines of actual matched code. Include path + line range IF
   the tool provided them. Never invent line numbers.

5. Conclusion leads with epistemic status:
   "For the [dimension], evidence = [Direct Proof / Infrastructure Hint /
   Partial Implementation / Global Absence]; matches in [files] show [what];
   structural footprint scan of [invariants] returned [result]."

Fallback (Safe Mode):
Answer is "let me check first", NOT "X isn't built", if any of:
- Unable to name the dimension precisely
- Footprint scan returned matches you haven't read
- Unsure which architectural pattern applies AND haven't searched alternatives
- The user pushed back on a similar claim recently

Self-check triggers:
- "I'd remember if we built this"
- "BACKLOG looks confident"
- "I just need to check one file"
- "My mental model of this system feels obvious" (← especially this one)

Honest limits:
- Wrong mental model of the architecture can still produce structurally
  rigorous wrong audits. The stack-discipline sub-step is a hedge, not a fix.
- Generated code, external services, dynamic dispatch, and indirection can
  evade footprint scans even when the feature exists.
- "Global" means global-within-visible-code, not global-within-system.
- Discipline is in the practice, not the prose. A 700-token rule
  half-followed is worse than a 200-token rule actually followed.
- This rule reduces but does not eliminate misclaims.
- When the architectural ontology is unclear, ask the user before concluding.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is the rule. Now the reasoning.&lt;/p&gt;

&lt;p&gt;I had Claude Code as my coding agent on a personal automation project. By 11 AM one morning, the agent had confidently claimed "feature X is not built" four times in a row, each time wrong, each time caught only by my pushback. The pattern was identical: trust the project's BACKLOG framing, do a narrow grep, miss adjacent layers, declare absence.&lt;/p&gt;

&lt;p&gt;The standard hallucination story does not fit. The agent searched. It searched fine. It just searched for the wrong shapes.&lt;/p&gt;

&lt;p&gt;What I observed: the agent was searching by name when it should be searching by shape. A feature can be called anything. A feature cannot exist without leaving structural residue. There has to be a route, a schema, a registered tool, a scheduled job, a documented decision. When the agent searches by name, it is asking what string would this feature use (a question about vocabulary). When it searches by shape, it is asking what artifact would this feature require (a question about architecture).&lt;/p&gt;

&lt;p&gt;The rule above forces the second question.&lt;/p&gt;

&lt;p&gt;I ran the rule through eight critiques across four rounds before settling on this version. The biggest substantive shift was structural-footprint-vs-synonyms. The earlier draft had me generating better synonyms when stuck. That just relocates the dependency on the agent's imagination. The structural-footprint version asks a different question: what artifact would prove the feature exists? Then grep for that artifact. The dependency moves from imagination to architectural knowledge, which is more reliable.&lt;/p&gt;

&lt;p&gt;The other major addition was the absence-scope distinction: "I searched module X and found nothing" is a scope claim, not a fact claim. The fix is making absence claims global on the architectural invariant.&lt;/p&gt;

&lt;p&gt;The rule has known limits. They are listed in the rule itself. The biggest one is wrong-ontology rigor: an agent could generate a structurally rigorous footprint search against the wrong architectural pattern (e.g., search GraphQL patterns on a REST system) and confidently confirm absence. The stack-discipline sub-step is a hedge, not a fix.&lt;/p&gt;

&lt;p&gt;What I want from you:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Try it.&lt;/strong&gt; Run it as a system rule on a project where you use an AI coding agent for a few sessions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tell me what breaks.&lt;/strong&gt; Specifically: hallucination shapes the structural footprint search would NOT catch, audit-theater patterns where the form is satisfied without the substance, over-triggering on questions that were not actually absence claims.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tell me what you have written.&lt;/strong&gt; If you have rules in your own CLAUDE.md or system prompt that solve adjacent problems, I want to read them.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I am running this on a separate project for two to three weeks before deciding whether to graduate it to my global agent configuration. After that I will know whether to keep it, refine it, or archive it. Your test reports compress that timeline.&lt;/p&gt;

&lt;p&gt;Reply or DM on whichever platform you found this.&lt;/p&gt;

&lt;p&gt;The misspelling stays.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>programming</category>
      <category>claude</category>
    </item>
    <item>
      <title>Pre-Build Existence Audit Rule : looking for the failure modes I'm still missing</title>
      <dc:creator>Nate Voss</dc:creator>
      <pubDate>Wed, 06 May 2026 12:02:46 +0000</pubDate>
      <link>https://dev.to/natevoss/pre-build-existence-audit-rule-looking-for-the-failure-modes-im-still-missing-4kc5</link>
      <guid>https://dev.to/natevoss/pre-build-existence-audit-rule-looking-for-the-failure-modes-im-still-missing-4kc5</guid>
      <description>&lt;p&gt;I wrote a rule for AI coding agents two days ago. It is untested in production sessions. I am posting it here to find its failure modes faster than I would by waiting for my own future mistakes to surface them.&lt;/p&gt;

&lt;p&gt;The rule is below first. Story and reasoning after.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Pre-Build Existence Audit Rule (v1, structural verification)

Status: Untested in production sessions. Test on a new project for 2-3 weeks
before considering global rollout.

Before claiming "feature X is not built / not implemented / missing":

1. Map
   rg -li "&amp;lt;keyword&amp;gt;" .                            # project repo
   rg -li "&amp;lt;keyword&amp;gt;" ~/.claude/projects/*/memory/ # agent memory
   If either &amp;gt;5 files match, use the file list to scope which to read.

2. Structural footprint scan (NOT just synonyms)
   Identify architectural invariants this feature class would require:
   - Integration/API → router definitions, endpoint registrations,
     plugin tool lists
   - Data → schema files, migrations, type definitions, persisted-entity fields
   - Background → cron entries, queue handlers, scheduled job registrations
   - Cross-service → service registry, infra config, IPC handlers
   - Memory/decisions → project_*.md files documenting prior shipment

   Stack discipline: footprints must be stack-appropriate. If unsure which
   architectural pattern applies, list 2-3 plausible alternatives
   (REST/GraphQL/RPC; cron/queue/webhook) and search each. Wrong-ontology
   audits feel rigorous but miss truth.

   Grep each invariant. If ANY return matches, "not built" is contradicted
   until you've read those matches.

3. Epistemic categorization. Label each match as ONE of:
   - Direct Proof: read the exact logic for the dimension being asked
   - Infrastructure Hint: schema/hooks/types only, not the specific logic
   - Partial Implementation: some footprints present, others missing
   - Global Absence: searched ALL relevant invariants across ENTIRE repo,
     found no footprint

4. Cite without fabricating
   Quote 3-5 lines of actual matched code. Include path + line range IF
   the tool provided them. Never invent line numbers.

5. Conclusion leads with epistemic status:
   "For the [dimension], evidence = [Direct Proof / Infrastructure Hint /
   Partial Implementation / Global Absence]; matches in [files] show [what];
   structural footprint scan of [invariants] returned [result]."

Fallback (Safe Mode):
Answer is "let me check first", NOT "X isn't built", if any of:
- Unable to name the dimension precisely
- Footprint scan returned matches you haven't read
- Unsure which architectural pattern applies AND haven't searched alternatives
- The user pushed back on a similar claim recently

Self-check triggers:
- "I'd remember if we built this"
- "BACKLOG looks confident"
- "I just need to check one file"
- "My mental model of this system feels obvious" (← especially this one)

Honest limits:
- Wrong mental model of the architecture can still produce structurally
  rigorous wrong audits. The stack-discipline sub-step is a hedge, not a fix.
- Generated code, external services, dynamic dispatch, and indirection can
  evade footprint scans even when the feature exists.
- "Global" means global-within-visible-code, not global-within-system.
- Discipline is in the practice, not the prose. A 700-token rule
  half-followed is worse than a 200-token rule actually followed.
- This rule reduces but does not eliminate misclaims.
- When the architectural ontology is unclear, ask the user before concluding.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is the rule. Now the reasoning.&lt;/p&gt;

&lt;p&gt;I had Claude Code as my coding agent on a personal automation project. By 11 AM one morning, the agent had confidently claimed "feature X is not built" four times in a row, each time wrong, each time caught only by my pushback. The pattern was identical: trust the project's BACKLOG framing, do a narrow grep, miss adjacent layers, declare absence.&lt;/p&gt;

&lt;p&gt;The standard hallucination story does not fit. The agent searched. It searched fine. It just searched for the wrong shapes.&lt;/p&gt;

&lt;p&gt;What I observed: the agent was searching by name when it should be searching by shape. A feature can be called anything. A feature cannot exist without leaving structural residue. There has to be a route, a schema, a registered tool, a scheduled job, a documented decision. When the agent searches by name, it is asking what string would this feature use (a question about vocabulary). When it searches by shape, it is asking what artifact would this feature require (a question about architecture).&lt;/p&gt;

&lt;p&gt;The rule above forces the second question.&lt;/p&gt;

&lt;p&gt;I ran the rule through eight critiques across four rounds before settling on this version. The biggest substantive shift was structural-footprint-vs-synonyms. The earlier draft had me generating better synonyms when stuck. That just relocates the dependency on the agent's imagination. The structural-footprint version asks a different question: what artifact would prove the feature exists? Then grep for that artifact. The dependency moves from imagination to architectural knowledge, which is more reliable.&lt;/p&gt;

&lt;p&gt;The other major addition was the absence-scope distinction: "I searched module X and found nothing" is a scope claim, not a fact claim. The fix is making absence claims global on the architectural invariant.&lt;/p&gt;

&lt;p&gt;The rule has known limits. They are listed in the rule itself. The biggest one is wrong-ontology rigor: an agent could generate a structurally rigorous footprint search against the wrong architectural pattern (e.g., search GraphQL patterns on a REST system) and confidently confirm absence. The stack-discipline sub-step is a hedge, not a fix.&lt;/p&gt;

&lt;p&gt;What I want from you:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Try it.&lt;/strong&gt; Run it as a system rule on a project where you use an AI coding agent for a few sessions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tell me what breaks.&lt;/strong&gt; Specifically: hallucination shapes the structural footprint search would NOT catch, audit-theater patterns where the form is satisfied without the substance, over-triggering on questions that were not actually absence claims.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tell me what you have written.&lt;/strong&gt; If you have rules in your own CLAUDE.md or system prompt that solve adjacent problems, I want to read them.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I am running this on a separate project for two to three weeks before deciding whether to graduate it to my global agent configuration. After that I will know whether to keep it, refine it, or archive it. Your test reports compress that timeline.&lt;/p&gt;

&lt;p&gt;Reply or DM on whichever platform you found this.&lt;/p&gt;

&lt;p&gt;The misspelling stays.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>programming</category>
      <category>claude</category>
    </item>
    <item>
      <title>4 rules I added to my CLAUDE.md after a week of weird CLI bugs</title>
      <dc:creator>Nate Voss</dc:creator>
      <pubDate>Wed, 06 May 2026 10:45:50 +0000</pubDate>
      <link>https://dev.to/natevoss/4-rules-i-added-to-my-claudemd-after-a-week-of-weird-cli-bugs-p6c</link>
      <guid>https://dev.to/natevoss/4-rules-i-added-to-my-claudemd-after-a-week-of-weird-cli-bugs-p6c</guid>
      <description>&lt;p&gt;I shipped a small CLI tool last week and ran it for the first time on my own machine. The output had a number that read &lt;code&gt;1,28,000&lt;/code&gt; instead of &lt;code&gt;128,000&lt;/code&gt;. I stared at it for a minute, ran the same code in a node REPL, got the same wrong number back, and realized my locale was doing it. A few hours later I had four entries in my CLAUDE.md file that I should have written months ago.&lt;/p&gt;

&lt;p&gt;Here they are.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Always pass an explicit locale to &lt;code&gt;toLocaleString&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Bare &lt;code&gt;(128000).toLocaleString()&lt;/code&gt; is a trap. It uses whatever the system locale happens to be. On my machine that's en-IN, which renders &lt;code&gt;128000&lt;/code&gt; as &lt;code&gt;1,28,000&lt;/code&gt;. On a US-locale machine the same code returns &lt;code&gt;128,000&lt;/code&gt;. The bug only shows up where the locale is set, which means CI passes, your unit tests on a fresh container pass, and the wrong separators land in production output.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// don't&lt;/span&gt;
&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;// do&lt;/span&gt;
&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en-US&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rule I added: any time you generate number-formatting code for CLI or any user-facing text, pass an explicit locale. Never call it bare.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Keep CLI output for AI-editor tools under five lines
&lt;/h2&gt;

&lt;p&gt;I learned this one by watching myself ignore my own tool. I'd built a small command for inspecting build artifacts and ran it inside an AI assistant's terminal. The result was a 12-line printout with the answer near the bottom. The assistant collapsed it behind a &lt;code&gt;Ctrl+O to expand&lt;/code&gt; prompt, and I never expanded it. The agent reading the output never saw the result either.&lt;/p&gt;

&lt;p&gt;If a CLI is designed to run inside an AI assistant's bash, the design constraint is that assistant's read window, not your own terminal. Result plus summary in 4 to 5 lines max. Verbose mode behind a flag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✓ build ok
3 packages, 412kb gzipped
fastest: core (180ms)
slowest: ui (910ms)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That fits. Anything more elaborate gets folded behind the expand prompt and effectively disappears from both you and the model.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. &lt;code&gt;npx &amp;lt;package&amp;gt;&lt;/code&gt; fails inside the package's own monorepo
&lt;/h2&gt;

&lt;p&gt;I burned half an afternoon on this one. I was developing the CLI inside a pnpm workspace, ran &lt;code&gt;npx my-cli&lt;/code&gt; to smoke-test it, and got resolver errors. The package built fine. The bin field was correct. Outside the repo it ran clean. Inside the workspace, the resolver had different ideas about which version of which thing to use, because workspace context confuses it.&lt;/p&gt;

&lt;p&gt;The fix is not a fix, it's a docs entry. If a CLI lives in a monorepo, your README should say &lt;code&gt;install globally with npm install -g&lt;/code&gt; or run from outside the project directory. The rule I added to CLAUDE.md tells the assistant to never suggest &lt;code&gt;npx &amp;lt;pkgname&amp;gt;&lt;/code&gt; as a smoke test from inside the same repo that defines the package.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Shared-library fixes need version bumps on both sides
&lt;/h2&gt;

&lt;p&gt;I had a CLI that depends on a small library of mine as an external npm package, not a bundled module. I found a bug in the library, fixed it, ran the CLI's tests against the local working tree, everything passed, and shipped. The bug was still live.&lt;/p&gt;

&lt;p&gt;The CLI's &lt;code&gt;package.json&lt;/code&gt; was pinned to the previous library version. Fixing the library does nothing downstream until you publish a new version of the library AND bump the consumer's dependency to match. Local test runs lie because they resolve to your working tree, not the published artifact.&lt;/p&gt;

&lt;p&gt;The rule, copy-paste:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;If a fix touches a shared library that the consumer depends on as
an external npm package (not vendored, not workspace-linked):
  1. Publish the library with a new version
  2. Bump the consumer's dep range
  3. Publish the consumer
Otherwise the fix doesn't ship.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I added that to CLAUDE.md as a checklist the assistant walks through before claiming a bug is fixed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;If you want to copy one of these into your own setup, here's the format that works in CLAUDE.md, cursor rules, or copilot instructions:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When generating any number-formatting code for CLI output or user-facing text, always pass an explicit locale to &lt;code&gt;toLocaleString&lt;/code&gt; (typically &lt;code&gt;'en-US'&lt;/code&gt;). Never call it bare. System locale varies by region and produces wrong thousands separators (e.g. &lt;code&gt;1,28,000&lt;/code&gt; instead of &lt;code&gt;128,000&lt;/code&gt;).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Add it once, save yourself the next version of this same day.&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>ai</category>
      <category>productivity</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Model Routing: 3 Things I Learned Sending Tasks to the Cheapest Model That Actually Works</title>
      <dc:creator>Nate Voss</dc:creator>
      <pubDate>Mon, 04 May 2026 06:54:30 +0000</pubDate>
      <link>https://dev.to/natevoss/model-routing-3-things-i-learned-sending-tasks-to-the-cheapest-model-that-actually-works-4e31</link>
      <guid>https://dev.to/natevoss/model-routing-3-things-i-learned-sending-tasks-to-the-cheapest-model-that-actually-works-4e31</guid>
      <description>&lt;p&gt;Everyone benchmarks models. Sonnet beats Haiku on reasoning. Opus beats Sonnet. Haiku is fastest. These things are all true.&lt;/p&gt;

&lt;p&gt;But benchmarking and deploying are different games. At scale, the difference between Haiku at $0.80/million tokens and Sonnet at $3/million tokens isn't academic. It's $400+ monthly on a mid-size application. The trap is paying for capability you don't actually need because you never measured what you do need.&lt;/p&gt;

&lt;p&gt;I built a router to answer one question: which tasks in my actual workflow could run on the cheapest model without failing? The answer surprised me. And I learned that the real value isn't the savings. It's the forcing function. You can't implement routing without auditing exactly where your complexity lives.&lt;/p&gt;

&lt;h2&gt;
  
  
  3 Things I Learned
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Your Intuition About Task Complexity Is Backwards
&lt;/h3&gt;

&lt;p&gt;You think something needs Sonnet. Your gut says: "this requires reasoning, obviously expensive model."&lt;/p&gt;

&lt;p&gt;So I measured. Content classification? Haiku handles 95% of real requests. Writing summaries? 88%. Extracting structured data? 92%. The edge cases that needed Sonnet were smaller than I'd guessed. And they were always the same types of edge cases.&lt;/p&gt;

&lt;p&gt;Here's the pattern I found: obvious cases are &lt;strong&gt;really&lt;/strong&gt; obvious to Haiku. Spam detection, data validation, simple extractions. Haiku nails these. The failures cluster in a small, identifiable category: ambiguous cases where the human answer is ambiguous. That's when you need Sonnet's nuance.&lt;/p&gt;

&lt;p&gt;But you don't know your edge case percentage until you try. Guessing leaves money on the table.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. You Need Observability Before Routing Saves Anything
&lt;/h3&gt;

&lt;p&gt;The instinct is to build the router first. "Let's write logic that detects complex requests and routes to Sonnet."&lt;/p&gt;

&lt;p&gt;This is backward. You need to measure first. Log every task with both Haiku and Sonnet responses side-by-side. Compare them. Find the patterns.&lt;/p&gt;

&lt;p&gt;Real questions to answer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When did Haiku refuse a task that Sonnet handled?&lt;/li&gt;
&lt;li&gt;How often do their answers differ, and which one was right?&lt;/li&gt;
&lt;li&gt;Was Haiku just uncertain, or actually wrong?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This requires instrumenting your inference layer. It takes a week. But you can't optimize what you can't see. Most teams skip this and build routers on intuition, which is why their routers are fragile.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Routing Rules Should Be Dumb, Not Smart
&lt;/h3&gt;

&lt;p&gt;The temptation: build a classifier that predicts task complexity. Input length heuristics, keyword matching, embedding similarity. Something sophisticated.&lt;/p&gt;

&lt;p&gt;Don't. Use a simple rule: &lt;strong&gt;"If the model reports low confidence, escalate to Sonnet."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This separates the decision from the task. Haiku tells you when it's uncertain. That's a signal you can act on immediately, without needing to predict the future.&lt;/p&gt;

&lt;p&gt;The dumb rule wins because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It adapts as your tasks change (no retraining)&lt;/li&gt;
&lt;li&gt;It's testable (you can verify the confidence threshold)&lt;/li&gt;
&lt;li&gt;It fails safely (escalation costs more but works)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The smart rule loses because routing logic becomes load-bearing infrastructure. Requires constant tuning. Breaks when your data distribution shifts.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Anthropic&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@anthropic-ai/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;classifyWithFallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;confidenceThreshold&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="c1"&gt;// First pass: try Haiku (cheap, fast)&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;haikuResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
 &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;claude-3-5-haiku-20241022&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
 &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Classify this text as: safe, unsafe, or review-needed. Return JSON with {classification, confidence}.

Text: "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"`&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;]&lt;/span&gt;
 &lt;span class="p"&gt;});&lt;/span&gt;

 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;haikuResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;haikuResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

 &lt;span class="c1"&gt;// Log all Haiku decisions (even successes)&lt;/span&gt;
 &lt;span class="c1"&gt;// You're building a dataset of "when does Haiku work?"&lt;/span&gt;
 &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
 &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;haiku&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;classification&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;haikuResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classification&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;confidence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;haikuResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;confidence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;tokensUsed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="nx"&gt;haikuResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;input_tokens&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
 &lt;span class="nx"&gt;haikuResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;output_tokens&lt;/span&gt;
 &lt;span class="p"&gt;});&lt;/span&gt;

 &lt;span class="c1"&gt;// If Haiku is unsure, escalate to Sonnet&lt;/span&gt;
 &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;haikuResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;confidence&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;confidenceThreshold&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sonnetResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
 &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;claude-3-5-sonnet-20241022&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
 &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Classify this text as: safe, unsafe, or review-needed. Return JSON with {classification, confidence}.

Text: "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"`&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;]&lt;/span&gt;
 &lt;span class="p"&gt;});&lt;/span&gt;

 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sonnetResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sonnetResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
 &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sonnet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;escalatedFrom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;haiku&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;classification&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sonnetResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classification&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;tokensUsed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="nx"&gt;sonnetResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;input_tokens&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
 &lt;span class="nx"&gt;sonnetResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;output_tokens&lt;/span&gt;
 &lt;span class="p"&gt;});&lt;/span&gt;

 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;sonnetResult&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;

 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;haikuResult&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Run both models in parallel during development and log the results. In production, start with Haiku, escalate on low confidence. As your logs accumulate, you'll see exactly which tasks need expensive models and which don't.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Math
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Haiku: $0.80 per 1M input tokens
Sonnet: $3 per 1M input tokens

Scenario: 1M requests/month, 200 tokens average
- All Sonnet: 1M × 200 tokens = $600
- 95% Haiku: (950k × 200) Haiku + (50k × 200) Sonnet = $152 + $30 = $182
- Savings: $418/month

At enterprise scale (100M requests/month): $41,800/month saved by routing to the cheapest viable model.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The cost difference compounds. Small routing decisions get multiplied across thousands of requests.&lt;/p&gt;

&lt;h2&gt;
  
  
  One Common Pitfall
&lt;/h2&gt;

&lt;p&gt;You'll build a sophisticated router and wonder why it doesn't move the needle. Usually because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You spent three months on routing logic, but you spend one week validating it&lt;/li&gt;
&lt;li&gt;The escalation threshold is too aggressive ("if anything looks hard, use Sonnet")&lt;/li&gt;
&lt;li&gt;You're routing on heuristics, not observed behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The fix: measure first, always. Log both models' responses in parallel before committing to either one. You'll find that the obvious cases are really obvious, and the edge cases are smaller than you think.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Routing Actually Works
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Build it if:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have &amp;gt;100k requests/month (smaller volume doesn't justify overhead)&lt;/li&gt;
&lt;li&gt;Your requests fall into clusters (some are cheap tasks, some are hard)&lt;/li&gt;
&lt;li&gt;You can measure ground truth (compare Haiku vs Sonnet, track which was right)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Don't build it if:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&amp;lt;10k requests/month (infrastructure overhead isn't worth it)&lt;/li&gt;
&lt;li&gt;Every request is unique and complex (no pattern to exploit)&lt;/li&gt;
&lt;li&gt;You need 99.9% accuracy (can't tolerate Haiku failures)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Real Win
&lt;/h2&gt;

&lt;p&gt;The cost savings are real. But the bigger win is the audit itself. Building a router forces you to measure exactly where your complexity actually lives. Most teams overthink what they need because they never measure. The router is just the excuse to finally look.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>tutorial</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>3 Things I Learned Auditing My LLM App's Token Spend (And Why Your Benchmarks Are Lying)</title>
      <dc:creator>Nate Voss</dc:creator>
      <pubDate>Mon, 27 Apr 2026 08:04:50 +0000</pubDate>
      <link>https://dev.to/natevoss/3-things-i-learned-auditing-my-llm-apps-token-spend-and-why-your-benchmarks-are-lying-3nbi</link>
      <guid>https://dev.to/natevoss/3-things-i-learned-auditing-my-llm-apps-token-spend-and-why-your-benchmarks-are-lying-3nbi</guid>
      <description>&lt;p&gt;You know that feeling when you ship an AI feature and realize your token bill is 3x what you estimated? Yeah, that was me last week.&lt;/p&gt;

&lt;p&gt;I have this thing called Agent-Max — it's a multi-platform growth agent that runs autonomous workflows: generating content, publishing to Bluesky, Medium, Twitter, Reddit. Sounds heavy, right? Every Monday it synthesizes a week of reading, scrapes engagement metrics, decides what to post and where. Seven platforms. Infinite LLM calls if you're not paying attention.&lt;/p&gt;

&lt;p&gt;Last Sunday I realized I had no idea what I was actually spending. I knew &lt;em&gt;roughly&lt;/em&gt; — "somewhere between $5-20/week" — but roughly is how you end up with bill shock. So I built PromptFuel to solve the actual problem: measure what your app is doing, not what the docs say it &lt;em&gt;should&lt;/em&gt; do.&lt;/p&gt;

&lt;p&gt;Here's what three days of auditing my own code taught me.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Your bottleneck isn't the model you picked, it's the prompt you didn't trim
&lt;/h2&gt;

&lt;p&gt;I assumed my biggest cost sink was the weekly reflection. Claude reads 7 days of snapshots, engagement data, content history, trend analysis, then reasons about next week's strategy. Heavy prompt, right?&lt;/p&gt;

&lt;p&gt;Nope.&lt;/p&gt;

&lt;p&gt;Running &lt;code&gt;pf optimize&lt;/code&gt; on the actual prompts showed the reflection was 2,847 tokens. Not small, but fine. The real killer: the daily content pregeneration loop was calling Claude 5 times per platform, and each call had:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Entire engagement history (redundant. I'm fetching fresh data every run)&lt;/li&gt;
&lt;li&gt;Every. Single. Previous. Post. (all 120 of them, in the context)&lt;/li&gt;
&lt;li&gt;Current date, weather, trending topics (reloaded every call)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cutting history to "last 10 posts, last 3 days of engagement" knocked 40% off. Not because I switched models. Because I stopped hallucinating I needed context I wasn't even &lt;em&gt;reading&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Your audit will surface the dumb stuff, not the obvious stuff
&lt;/h2&gt;

&lt;p&gt;Benchmarks tell you Claude costs 3¢ per 1M input tokens. Haiku costs 0.8¢. Pick the right model, do the math, move on.&lt;/p&gt;

&lt;p&gt;Except I was calling Claude Sonnet 7 times/week on background analytics where Haiku was plenty. Not intentional. I'd copied the model from an earlier prompt and never thought about it again. One-line change, zero quality loss, $2 saved per month.&lt;/p&gt;

&lt;p&gt;That math &lt;em&gt;never&lt;/em&gt; shows up in a benchmark. It shows up in your actual codebase, on your actual data, running your actual job. PromptFuel's advantage isn't telling you models are expensive. It's finding the calls you forgot about and showing you the before/after side-by-side.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Once you see the numbers, the optimization loop becomes obvious
&lt;/h2&gt;

&lt;p&gt;The first time I ran the dashboard, I thought I was done. Then Monday's weekly job ran and I watched 47 new prompts execute. Dashboard updated in real time. I saw the pattern. There's another cut.&lt;/p&gt;

&lt;p&gt;Auditing once is useful. Auditing every week is how you stop bleeding money.&lt;/p&gt;




&lt;h2&gt;
  
  
  Let's walk through it
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Install:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; promptfuel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Run pf optimize&lt;/strong&gt; on a real prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pf optimize ./src/prompts/reflect.md &lt;span class="nt"&gt;--model&lt;/span&gt; claude-3-5-sonnet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll see token count, cost per call, and a readability score. More importantly, you'll see where the redundancy is hiding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open the dashboard&lt;/strong&gt; to watch prompts in real time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pf dashboard &lt;span class="nt"&gt;--watch&lt;/span&gt; ./src/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Port 3000 opens. Every time you call an LLM, you see it log: model, input tokens, output tokens, cost, latency. No guessing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For production, wire up the SDK:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PromptFuel&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;promptfuel/sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Anthropic&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@anthropic-ai/sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PromptFuel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wrapClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
 &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;claude-3-5-sonnet-20241022&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your prompt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Automatically tracked. One line changes nothing&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getMetrics&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; 
&lt;span class="c1"&gt;// { totalTokens: 342, totalCost: $0.008, calls: 1 }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Real numbers
&lt;/h2&gt;

&lt;p&gt;Agent-Max before: ~1,847 tokens/week across all platforms.&lt;/p&gt;

&lt;p&gt;Agent-Max after (trimmed + downgraded safe calls to Haiku): 1,094 tokens/week.&lt;/p&gt;

&lt;p&gt;40% reduction. No quality loss. Three hours to audit and implement.&lt;/p&gt;

&lt;p&gt;That's not a benchmark. That's a real app, real prompts, real data.&lt;/p&gt;




&lt;p&gt;Stop guessing about your token spend. Measure what you're actually doing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; promptfuel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://promptfuel.vercel.app?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=max" rel="noopener noreferrer"&gt;https://promptfuel.vercel.app?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=max&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>tutorial</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>3 Things I Learned Auditing My LLM App's Token Spend (And Why Your Benchmarks Are Lying)</title>
      <dc:creator>Nate Voss</dc:creator>
      <pubDate>Mon, 27 Apr 2026 06:29:33 +0000</pubDate>
      <link>https://dev.to/natevoss/3-things-i-learned-auditing-my-llm-apps-token-spend-and-why-your-benchmarks-are-lying-453l</link>
      <guid>https://dev.to/natevoss/3-things-i-learned-auditing-my-llm-apps-token-spend-and-why-your-benchmarks-are-lying-453l</guid>
      <description>&lt;p&gt;You know that feeling when you ship an AI feature and realize your token bill is 3x what you estimated? Yeah, that was me last week.&lt;/p&gt;

&lt;p&gt;I have this thing called Agent-Max — it's a multi-platform growth agent that runs autonomous workflows: generating content, publishing to Bluesky, Medium, Twitter, Reddit. Sounds heavy, right? Every Monday it synthesizes a week of reading, scrapes engagement metrics, decides what to post and where. Seven platforms. Infinite LLM calls if you're not paying attention.&lt;/p&gt;

&lt;p&gt;Last Sunday I realized I had no idea what I was actually spending. I knew &lt;em&gt;roughly&lt;/em&gt; — "somewhere between $5-20/week" — but roughly is how you end up with bill shock. So I built PromptFuel to solve the actual problem: measure what your app is doing, not what the docs say it &lt;em&gt;should&lt;/em&gt; do.&lt;/p&gt;

&lt;p&gt;Here's what three days of auditing my own code taught me.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Your bottleneck isn't the model you picked, it's the prompt you didn't trim
&lt;/h2&gt;

&lt;p&gt;I assumed my biggest cost sink was the weekly reflection. Claude reads 7 days of snapshots, engagement data, content history, trend analysis, then reasons about next week's strategy. Heavy prompt, right?&lt;/p&gt;

&lt;p&gt;Nope.&lt;/p&gt;

&lt;p&gt;Running &lt;code&gt;pf optimize&lt;/code&gt; on the actual prompts showed the reflection was 2,847 tokens. Not small, but fine. The real killer: the daily content pregeneration loop was calling Claude 5 times per platform, and each call had:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Entire engagement history (redundant. I'm fetching fresh data every run)&lt;/li&gt;
&lt;li&gt;Every. Single. Previous. Post. (all 120 of them, in the context)&lt;/li&gt;
&lt;li&gt;Current date, weather, trending topics (reloaded every call)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cutting history to "last 10 posts, last 3 days of engagement" knocked 40% off. Not because I switched models. Because I stopped hallucinating I needed context I wasn't even &lt;em&gt;reading&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Your audit will surface the dumb stuff, not the obvious stuff
&lt;/h2&gt;

&lt;p&gt;Benchmarks tell you Claude costs 3¢ per 1M input tokens. Haiku costs 0.8¢. Pick the right model, do the math, move on.&lt;/p&gt;

&lt;p&gt;Except I was calling Claude Sonnet 7 times/week on background analytics where Haiku was plenty. Not intentional. I'd copied the model from an earlier prompt and never thought about it again. One-line change, zero quality loss, $2 saved per month.&lt;/p&gt;

&lt;p&gt;That math &lt;em&gt;never&lt;/em&gt; shows up in a benchmark. It shows up in your actual codebase, on your actual data, running your actual job. PromptFuel's advantage isn't telling you models are expensive. It's finding the calls you forgot about and showing you the before/after side-by-side.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Once you see the numbers, the optimization loop becomes obvious
&lt;/h2&gt;

&lt;p&gt;The first time I ran the dashboard, I thought I was done. Then Monday's weekly job ran and I watched 47 new prompts execute. Dashboard updated in real time. I saw the pattern. There's another cut.&lt;/p&gt;

&lt;p&gt;Auditing once is useful. Auditing every week is how you stop bleeding money.&lt;/p&gt;




&lt;h2&gt;
  
  
  Let's walk through it
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Install:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; promptfuel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Run pf optimize&lt;/strong&gt; on a real prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pf optimize ./src/prompts/reflect.md &lt;span class="nt"&gt;--model&lt;/span&gt; claude-3-5-sonnet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll see token count, cost per call, and a readability score. More importantly, you'll see where the redundancy is hiding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open the dashboard&lt;/strong&gt; to watch prompts in real time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pf dashboard &lt;span class="nt"&gt;--watch&lt;/span&gt; ./src/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Port 3000 opens. Every time you call an LLM, you see it log: model, input tokens, output tokens, cost, latency. No guessing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For production, wire up the SDK:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PromptFuel&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;promptfuel/sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Anthropic&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@anthropic-ai/sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PromptFuel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wrapClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
 &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;claude-3-5-sonnet-20241022&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your prompt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Automatically tracked. One line changes nothing&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getMetrics&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; 
&lt;span class="c1"&gt;// { totalTokens: 342, totalCost: $0.008, calls: 1 }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Real numbers
&lt;/h2&gt;

&lt;p&gt;Agent-Max before: ~1,847 tokens/week across all platforms.&lt;/p&gt;

&lt;p&gt;Agent-Max after (trimmed + downgraded safe calls to Haiku): 1,094 tokens/week.&lt;/p&gt;

&lt;p&gt;40% reduction. No quality loss. Three hours to audit and implement.&lt;/p&gt;

&lt;p&gt;That's not a benchmark. That's a real app, real prompts, real data.&lt;/p&gt;




&lt;p&gt;Stop guessing about your token spend. Measure what you're actually doing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; promptfuel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://promptfuel.vercel.app?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=max" rel="noopener noreferrer"&gt;https://promptfuel.vercel.app?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=max&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>tutorial</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>3 Things I Learned Auditing My LLM App's Token Spend (And Why Your Benchmarks Are Lying)</title>
      <dc:creator>Nate Voss</dc:creator>
      <pubDate>Mon, 27 Apr 2026 06:13:27 +0000</pubDate>
      <link>https://dev.to/natevoss/3-things-i-learned-auditing-my-llm-apps-token-spend-and-why-your-benchmarks-are-lying-2kfd</link>
      <guid>https://dev.to/natevoss/3-things-i-learned-auditing-my-llm-apps-token-spend-and-why-your-benchmarks-are-lying-2kfd</guid>
      <description>&lt;p&gt;You know that feeling when you ship an AI feature and realize your token bill is 3x what you estimated? Yeah, that was me last week.&lt;/p&gt;

&lt;p&gt;I have this thing called Agent-Max — it's a multi-platform growth agent that runs autonomous workflows: generating content, publishing to Bluesky, Medium, Twitter, Reddit. Sounds heavy, right? Every Monday it synthesizes a week of reading, scrapes engagement metrics, decides what to post and where. Seven platforms. Infinite LLM calls if you're not paying attention.&lt;/p&gt;

&lt;p&gt;Last Sunday I realized I had no idea what I was actually spending. I knew &lt;em&gt;roughly&lt;/em&gt; — "somewhere between $5-20/week" — but roughly is how you end up with bill shock. So I built PromptFuel to solve the actual problem: measure what your app is doing, not what the docs say it &lt;em&gt;should&lt;/em&gt; do.&lt;/p&gt;

&lt;p&gt;Here's what three days of auditing my own code taught me.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Your bottleneck isn't the model you picked, it's the prompt you didn't trim
&lt;/h2&gt;

&lt;p&gt;I assumed my biggest cost sink was the weekly reflection. Claude reads 7 days of snapshots, engagement data, content history, trend analysis, then reasons about next week's strategy. Heavy prompt, right?&lt;/p&gt;

&lt;p&gt;Nope.&lt;/p&gt;

&lt;p&gt;Running &lt;code&gt;pf optimize&lt;/code&gt; on the actual prompts showed the reflection was 2,847 tokens. Not small, but fine. The real killer: the daily content pregeneration loop was calling Claude 5 times per platform, and each call had:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Entire engagement history (redundant. I'm fetching fresh data every run)&lt;/li&gt;
&lt;li&gt;Every. Single. Previous. Post. (all 120 of them, in the context)&lt;/li&gt;
&lt;li&gt;Current date, weather, trending topics (reloaded every call)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cutting history to "last 10 posts, last 3 days of engagement" knocked 40% off. Not because I switched models. Because I stopped hallucinating I needed context I wasn't even &lt;em&gt;reading&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Your audit will surface the dumb stuff, not the obvious stuff
&lt;/h2&gt;

&lt;p&gt;Benchmarks tell you Claude costs 3¢ per 1M input tokens. Haiku costs 0.8¢. Pick the right model, do the math, move on.&lt;/p&gt;

&lt;p&gt;Except I was calling Claude Sonnet 7 times/week on background analytics where Haiku was plenty. Not intentional. I'd copied the model from an earlier prompt and never thought about it again. One-line change, zero quality loss, $2 saved per month.&lt;/p&gt;

&lt;p&gt;That math &lt;em&gt;never&lt;/em&gt; shows up in a benchmark. It shows up in your actual codebase, on your actual data, running your actual job. PromptFuel's advantage isn't telling you models are expensive. It's finding the calls you forgot about and showing you the before/after side-by-side.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Once you see the numbers, the optimization loop becomes obvious
&lt;/h2&gt;

&lt;p&gt;The first time I ran the dashboard, I thought I was done. Then Monday's weekly job ran and I watched 47 new prompts execute. Dashboard updated in real time. I saw the pattern. There's another cut.&lt;/p&gt;

&lt;p&gt;Auditing once is useful. Auditing every week is how you stop bleeding money.&lt;/p&gt;




&lt;h2&gt;
  
  
  Let's walk through it
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Install:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; promptfuel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Run pf optimize&lt;/strong&gt; on a real prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pf optimize ./src/prompts/reflect.md &lt;span class="nt"&gt;--model&lt;/span&gt; claude-3-5-sonnet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll see token count, cost per call, and a readability score. More importantly, you'll see where the redundancy is hiding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open the dashboard&lt;/strong&gt; to watch prompts in real time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pf dashboard &lt;span class="nt"&gt;--watch&lt;/span&gt; ./src/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Port 3000 opens. Every time you call an LLM, you see it log: model, input tokens, output tokens, cost, latency. No guessing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For production, wire up the SDK:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PromptFuel&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;promptfuel/sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Anthropic&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@anthropic-ai/sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PromptFuel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wrapClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
 &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;claude-3-5-sonnet-20241022&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your prompt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Automatically tracked. One line changes nothing&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getMetrics&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; 
&lt;span class="c1"&gt;// { totalTokens: 342, totalCost: $0.008, calls: 1 }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Real numbers
&lt;/h2&gt;

&lt;p&gt;Agent-Max before: ~1,847 tokens/week across all platforms.&lt;/p&gt;

&lt;p&gt;Agent-Max after (trimmed + downgraded safe calls to Haiku): 1,094 tokens/week.&lt;/p&gt;

&lt;p&gt;40% reduction. No quality loss. Three hours to audit and implement.&lt;/p&gt;

&lt;p&gt;That's not a benchmark. That's a real app, real prompts, real data.&lt;/p&gt;




&lt;p&gt;Stop guessing about your token spend. Measure what you're actually doing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; promptfuel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://promptfuel.vercel.app?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=max" rel="noopener noreferrer"&gt;https://promptfuel.vercel.app?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=max&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>tutorial</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How I Accidentally Spent $800/Month on LLM Tokens I Didn't Need (And How to Fix It)</title>
      <dc:creator>Nate Voss</dc:creator>
      <pubDate>Thu, 23 Apr 2026 07:46:42 +0000</pubDate>
      <link>https://dev.to/natevoss/how-i-accidentally-spent-800month-on-llm-tokens-i-didnt-need-and-how-to-fix-it-oi7</link>
      <guid>https://dev.to/natevoss/how-i-accidentally-spent-800month-on-llm-tokens-i-didnt-need-and-how-to-fix-it-oi7</guid>
      <description>&lt;p&gt;I spent six weeks shipping the wrong thing.&lt;/p&gt;

&lt;p&gt;I built PromptFuel because I was hemorrhaging money on API calls. Not because I was building at scale—I wasn't. I was building &lt;em&gt;dumb&lt;/em&gt;. I'd write a prompt in isolation, test it once, ship it, then wonder why my OpenAI bill jumped $200. Turns out I was doing things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Asking GPT-4 to write validation logic that Haiku could handle just fine&lt;/li&gt;
&lt;li&gt;Sending full context windows when 30% of it was redundant&lt;/li&gt;
&lt;li&gt;Retrying identical requests with slightly different temperatures instead of picking one and sticking with it&lt;/li&gt;
&lt;li&gt;Including examples in prompts that the model was already trained on&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The real kick? None of this was visible. I had no idea which requests were wasteful, which models were overkill for my tasks, or where I was throwing money away. I just had a credit card statement and regret.&lt;/p&gt;

&lt;p&gt;So I built a tool to see what I was actually doing. And then I optimized it. Here's how.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem Nobody Talks About
&lt;/h2&gt;

&lt;p&gt;Choosing the right model for a job isn't about capabilities. A Haiku can validate JSON, classify text, and format output just as well as GPT-4o for most real work. The difference is cost: Haiku costs 10x less per token.&lt;/p&gt;

&lt;p&gt;But without visibility, you default to the expensive one. Because it's safe. Because you can't see the waste.&lt;/p&gt;

&lt;p&gt;After I started measuring, I found:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;35% of my requests didn't need GPT-4o.&lt;/strong&gt; They were hitting it because it was the default, not because it was the right tool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;20% of my prompts had bloat.&lt;/strong&gt; Instructions that contradicted each other, examples I copy-pasted but never used, context I included "just in case."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;15% of requests were duplicates.&lt;/strong&gt; Same input, same model, within minutes. If I'd cached or batched them, I'd cut token spend by half.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Total: &lt;strong&gt;40% waste.&lt;/strong&gt; $800 → $480. Not revolutionary, but real money for an indie project.&lt;/p&gt;

&lt;p&gt;The fix wasn't rocket science. It was boring infrastructure: measure, analyze, optimize, repeat.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: See What You're Actually Doing
&lt;/h2&gt;

&lt;p&gt;Install PromptFuel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; promptfuel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. No API keys, no auth, no bullshit. The tool runs locally.&lt;/p&gt;

&lt;p&gt;Now run this on any prompt or code snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pf optimize &lt;span class="nt"&gt;--input&lt;/span&gt; &lt;span class="s2"&gt;"Your prompt here"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or point it at a file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pf optimize &lt;span class="nt"&gt;--file&lt;/span&gt; my-prompt.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You get back:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Token count&lt;/strong&gt; — exactly what you'll be charged for&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost estimates&lt;/strong&gt; — broken down by model (Haiku, Sonnet, GPT-4o, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimization suggestions&lt;/strong&gt; — what you can trim without losing meaning&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model recommendations&lt;/strong&gt; — which model actually makes sense for this task&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Current prompt: 412 tokens

Optimization suggestions:
  - Remove redundant instruction (line 8)
  - Simplify JSON schema example (saves 34 tokens)
  - Collapse repeated context (saves 18 tokens)

Cost per call:
  - GPT-4o: $0.006 (❌ overpowered)
  - Claude 3.5 Sonnet: $0.002 (✓ recommended)
  - Claude 3 Haiku: $0.0004 (✓ if you only need classification)

Estimated monthly (1000 calls):
  - Current setup: $6.12
  - Optimized: $1.84
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the insight. That's what I was missing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Understand Your Actual Costs
&lt;/h2&gt;

&lt;p&gt;Open the dashboard:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pf dashboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your default browser opens to a local dashboard showing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;All your recent prompts&lt;/strong&gt; and their token counts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost distribution&lt;/strong&gt; — which requests ate the most budget&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model usage&lt;/strong&gt; — are you using the expensive ones too much?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimization opportunities&lt;/strong&gt; — ranked by potential savings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The dashboard doesn't need your API keys. It's analyzing local data. But it &lt;em&gt;will&lt;/em&gt; tell you which of your shipped prompts are costing way more than they should.&lt;/p&gt;

&lt;p&gt;Spend 10 minutes here. You'll probably find something you didn't realize you were doing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Integrate into Your Stack
&lt;/h2&gt;

&lt;p&gt;Once you see the waste, you'll want to catch it earlier. That's where the SDK and MCP server come in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option A: JavaScript SDK (for Next.js, Node apps)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @promptfuel/sdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PromptOptimizer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@promptfuel/sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;optimizer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PromptOptimizer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`You are a helpful assistant...
Classify the following text into categories...
[20 more lines of context you don't actually need]`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;analysis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;optimizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;analyze&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`This prompt costs $&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;analysis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;costPerCall&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gpt4o&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Optimized version: $&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;analysis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;optimized&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;costPerCall&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gpt4o&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Actually use the optimized version&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;optimizedPrompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;analysis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;optimized&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Option B: Claude Code MCP Server (for use in Claude directly)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're like me and you use Claude for a lot of your thinking, add the PromptFuel MCP server to your Claude Code settings. Then ask Claude directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@promptfuel optimize my prompt for cost

[paste your prompt]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude runs it through PromptFuel's analysis and tells you exactly where you're bleeding money. Then it generates an optimized version.&lt;/p&gt;

&lt;p&gt;Both approaches catch waste before it ships.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Happened Next
&lt;/h2&gt;

&lt;p&gt;After I actually measured and optimized my stuff, here's what I learned:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;You don't need the expensive model as often as you think.&lt;/strong&gt; Most of my classification, formatting, and even some reasoning tasks work fine on Haiku.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prompt bloat is real.&lt;/strong&gt; Every instruction that contradicts another one, every "just in case" example, every "let me explain the context" paragraph adds tokens and confusion.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token count scales weird.&lt;/strong&gt; I thought I'd save 10%. I saved 40%. Because once you see the pattern, you fix it everywhere.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For me: $800 → $480/month. For you, it might be different. But it won't be zero.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started (Right Now)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Install: &lt;code&gt;npm install -g promptfuel&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Optimize a single prompt: &lt;code&gt;pf optimize --file your-prompt.txt&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Open the dashboard: &lt;code&gt;pf dashboard&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;If you like it, integrate the SDK or MCP server into your workflow&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No commitment. No API keys. No upsell. Just a free tool that shows you where your money's going.&lt;/p&gt;

&lt;p&gt;The tool exists because I was tired of guessing. If you are too, give it a try: &lt;a href="https://promptfuel.vercel.app?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=max" rel="noopener noreferrer"&gt;https://promptfuel.vercel.app?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=max&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>tutorial</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>3 Things I Learned Benchmarking Claude, GPT-4o, and Gemini on Real Dev Work</title>
      <dc:creator>Nate Voss</dc:creator>
      <pubDate>Tue, 21 Apr 2026 12:07:05 +0000</pubDate>
      <link>https://dev.to/natevoss/3-things-i-learned-benchmarking-claude-gpt-4o-and-gemini-on-real-dev-work-38fl</link>
      <guid>https://dev.to/natevoss/3-things-i-learned-benchmarking-claude-gpt-4o-and-gemini-on-real-dev-work-38fl</guid>
      <description>&lt;p&gt;If you're still picking LLM providers by gut feeling, you're leaving money on the table. I ran 5 developer use cases through Claude 3.5 Sonnet, GPT-4o, and Gemini 2.0 Flash using PromptFuel to measure token usage and cost. The results? More interesting than "fastest wins." Here's what I found.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Setup
&lt;/h2&gt;

&lt;p&gt;I took 5 tasks I actually do in PromptFuel development:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;JSON schema validation prompt&lt;/strong&gt; — catch malformed API responses&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code review feedback&lt;/strong&gt; — multi-file analysis with context&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refactoring suggestion&lt;/strong&gt; — optimize a chunky utility function&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bug diagnosis&lt;/strong&gt; — trace through a stack trace with logs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation generation&lt;/strong&gt; — write API docs from code comments&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each got run through all three models with identical input. I used PromptFuel's CLI to count tokens and calculate costs, because doing this manually is chaos. Output quality was rated by me (subjectively, but honestly).&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Case Breakdown
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. JSON Schema Validation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; Schema definition + malformed JSON sample + expected error message format&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token usage (input → output):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Sonnet: 1,847 → 512 (cost: $0.0043)&lt;/li&gt;
&lt;li&gt;GPT-4o: 2,156 → 487 (cost: $0.0082)&lt;/li&gt;
&lt;li&gt;Gemini Flash: 1,923 → 501 (cost: $0.0001)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Quality:&lt;/strong&gt; All three nailed it. Claude was most concise in its explanation. GPT-4o over-explained. Gemini was crisp and useful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token efficiency win:&lt;/strong&gt; Gemini, by cost. Claude, by clarity per token.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Code Review (3 files, ~200 LOC)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; Three TypeScript modules + review instructions + examples of good feedback&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token usage:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Sonnet: 4,231 → 891 (cost: $0.0147)&lt;/li&gt;
&lt;li&gt;GPT-4o: 4,782 → 856 (cost: $0.0208)&lt;/li&gt;
&lt;li&gt;Gemini Flash: 4,456 → 823 (cost: $0.0003)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Quality:&lt;/strong&gt; Claude caught subtle issues I actually cared about. GPT-4o was thorough but verbose. Gemini gave surface-level feedback.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token efficiency win:&lt;/strong&gt; Gemini cheapest. Claude best output/token.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Refactoring Suggestion
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; 80-line utility function + performance requirements + current bottleneck description&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token usage:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Sonnet: 2,134 → 618 (cost: $0.0054)&lt;/li&gt;
&lt;li&gt;GPT-4o: 2,445 → 602 (cost: $0.0110)&lt;/li&gt;
&lt;li&gt;Gemini Flash: 2,287 → 587 (cost: $0.0002)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Quality:&lt;/strong&gt; Claude's refactor was production-ready. GPT-4o suggested good ideas but with syntax issues. Gemini's suggestion worked but wasn't elegant.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token efficiency win:&lt;/strong&gt; Gemini cost, Claude quality.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Bug Diagnosis
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; Stack trace (15 lines) + error logs (20 lines) + code snippet (40 lines) + attempted fixes tried&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token usage:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Sonnet: 2,856 → 445 (cost: $0.0071)&lt;/li&gt;
&lt;li&gt;GPT-4o: 3,102 → 421 (cost: $0.0127)&lt;/li&gt;
&lt;li&gt;Gemini Flash: 2,934 → 438 (cost: $0.0002)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Quality:&lt;/strong&gt; Claude nailed it immediately. GPT-4o circled around the issue. Gemini flagged the right file but not the root cause.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token efficiency win:&lt;/strong&gt; Gemini cost, Claude accuracy.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Documentation Generation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; 12 functions with JSDoc comments + expected markdown format + examples&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token usage:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Sonnet: 3,445 → 734 (cost: $0.0118)&lt;/li&gt;
&lt;li&gt;GPT-4o: 3,821 → 689 (cost: $0.0182)&lt;/li&gt;
&lt;li&gt;Gemini Flash: 3,567 → 712 (cost: $0.0004)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Quality:&lt;/strong&gt; Claude's docs were complete and well-structured. GPT-4o was good but required minimal cleanup. Gemini's docs were functional but missing details.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token efficiency win:&lt;/strong&gt; Gemini cost, Claude completeness.&lt;/p&gt;




&lt;h2&gt;
  
  
  The 3 Things I Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Cost-per-task != best value.&lt;/strong&gt; Gemini Flash is comically cheap (~90% less than GPT-4o), but you're paying for what you get. When I needed high-stakes work (code review, bug diagnosis), Claude was worth the extra cents because I didn't have to iterate. For throwaway tasks (generating examples, formatting), Gemini's cost made its mediocrity acceptable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Token count is not predictive of quality.&lt;/strong&gt; All three models produced similar token counts for the same input, but output quality varied wildly. GPT-4o consistently used more tokens and wasn't proportionally better. Claude packed useful signal into fewer tokens. This matters: if you're optimizing for cost alone, you'll pick the wrong model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Real-world testing beats benchmarks.&lt;/strong&gt; The model rankings flip depending on what you're actually doing. For documentation, Claude wins. For budget validation of a throwaway check, Gemini wins. Generic "fastest model" articles don't capture this. You need to test your actual tasks.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Benchmark Yours
&lt;/h2&gt;

&lt;p&gt;Here's the thing: this comparison is data, not law. Your tasks might weight differently. Let me show you how I tested this using PromptFuel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install PromptFuel (if you haven't)&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; promptfuel

&lt;span class="c"&gt;# Create a test file with your prompt&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; test-prompt.txt &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
[your prompt here]
&lt;/span&gt;&lt;span class="no"&gt;EOF

&lt;/span&gt;&lt;span class="c"&gt;# Count tokens across models&lt;/span&gt;
pf count test-prompt.txt &lt;span class="nt"&gt;--model&lt;/span&gt; claude-3-5-sonnet
pf count test-prompt.txt &lt;span class="nt"&gt;--model&lt;/span&gt; gpt-4o
pf count test-prompt.txt &lt;span class="nt"&gt;--model&lt;/span&gt; gemini-2.0-flash

&lt;span class="c"&gt;# Compare costs&lt;/span&gt;
pf count test-prompt.txt &lt;span class="nt"&gt;--compare&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;--compare&lt;/code&gt; flag gives you a cost matrix. Takes 30 seconds. Beats guessing.&lt;/p&gt;

&lt;p&gt;The real insight: &lt;strong&gt;run this for your specific use cases.&lt;/strong&gt; A document summarizer might favor Claude. A high-throughput classification pipeline might favor Gemini. The only way to know is to test.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Optimization
&lt;/h2&gt;

&lt;p&gt;After picking your model, there's still money left on the table. Here's a before/after from actual PromptFuel code:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before (unoptimized prompt):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are an expert code reviewer. Review the following code for quality, security, 
and performance issues. Check for common bugs, suggest improvements, and rate the 
code from 1-10. Consider edge cases, error handling, and best practices. Be thorough 
and detailed in your feedback.

[400 tokens of instructions]
[200 tokens of examples]
[150 tokens of code to review]
Total: ~750 input tokens
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After (optimized with PromptFuel):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Review code for quality, security, performance. Rate 1-10.

[Stripped redundant instructions]
[Examples reduced to 1 exemplar instead of 3]
[Code reformatted to remove whitespace]
Total: ~420 input tokens
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cost saved: ~$0.0012 per review on Claude. Run that 100 times a day, and you're saving $0.12/day, $36/year. Small? Yes. Multiplied by 50 internal tools? Now you're talking real money.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Honest Take
&lt;/h2&gt;

&lt;p&gt;Pick the model that gives you the output you need, then optimize the prompt. Stop optimizing for the wrong metric. Benchmarks are fun, but production bills are real.&lt;/p&gt;

&lt;p&gt;If you're running this analysis for your own stuff, PromptFuel makes it stupidly easy. It's free, no API keys needed, runs locally. Just &lt;code&gt;npm install -g promptfuel&lt;/code&gt; and compare. If you want the actual numbers from your prompts, run the test. Don't inherit my data — build your own.&lt;/p&gt;

&lt;p&gt;What's your highest-volume LLM task? Test it. You might be surprised which model wins.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; #ai #tutorial #javascript #optimization&lt;/p&gt;

</description>
      <category>ai</category>
      <category>tutorial</category>
      <category>javascript</category>
      <category>optimization</category>
    </item>
    <item>
      <title>3 Things I Learned Benchmarking Claude, GPT-4o, and Gemini on Real Dev Work</title>
      <dc:creator>Nate Voss</dc:creator>
      <pubDate>Tue, 21 Apr 2026 07:44:49 +0000</pubDate>
      <link>https://dev.to/natevoss/3-things-i-learned-benchmarking-claude-gpt-4o-and-gemini-on-real-dev-work-4cp5</link>
      <guid>https://dev.to/natevoss/3-things-i-learned-benchmarking-claude-gpt-4o-and-gemini-on-real-dev-work-4cp5</guid>
      <description>&lt;p&gt;If you're still picking LLM providers by gut feeling, you're leaving money on the table. I ran 5 developer use cases through Claude 3.5 Sonnet, GPT-4o, and Gemini 2.0 Flash using PromptFuel to measure token usage and cost. The results? More interesting than "fastest wins." Here's what I found.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Setup
&lt;/h2&gt;

&lt;p&gt;I took 5 tasks I actually do in PromptFuel development:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;JSON schema validation prompt&lt;/strong&gt; — catch malformed API responses&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code review feedback&lt;/strong&gt; — multi-file analysis with context&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refactoring suggestion&lt;/strong&gt; — optimize a chunky utility function&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bug diagnosis&lt;/strong&gt; — trace through a stack trace with logs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation generation&lt;/strong&gt; — write API docs from code comments&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each got run through all three models with identical input. I used PromptFuel's CLI to count tokens and calculate costs, because doing this manually is chaos. Output quality was rated by me (subjectively, but honestly).&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Case Breakdown
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. JSON Schema Validation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; Schema definition + malformed JSON sample + expected error message format&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token usage (input → output):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Sonnet: 1,847 → 512 (cost: $0.0043)&lt;/li&gt;
&lt;li&gt;GPT-4o: 2,156 → 487 (cost: $0.0082)&lt;/li&gt;
&lt;li&gt;Gemini Flash: 1,923 → 501 (cost: $0.0001)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Quality:&lt;/strong&gt; All three nailed it. Claude was most concise in its explanation. GPT-4o over-explained. Gemini was crisp and useful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token efficiency win:&lt;/strong&gt; Gemini, by cost. Claude, by clarity per token.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Code Review (3 files, ~200 LOC)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; Three TypeScript modules + review instructions + examples of good feedback&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token usage:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Sonnet: 4,231 → 891 (cost: $0.0147)&lt;/li&gt;
&lt;li&gt;GPT-4o: 4,782 → 856 (cost: $0.0208)&lt;/li&gt;
&lt;li&gt;Gemini Flash: 4,456 → 823 (cost: $0.0003)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Quality:&lt;/strong&gt; Claude caught subtle issues I actually cared about. GPT-4o was thorough but verbose. Gemini gave surface-level feedback.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token efficiency win:&lt;/strong&gt; Gemini cheapest. Claude best output/token.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Refactoring Suggestion
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; 80-line utility function + performance requirements + current bottleneck description&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token usage:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Sonnet: 2,134 → 618 (cost: $0.0054)&lt;/li&gt;
&lt;li&gt;GPT-4o: 2,445 → 602 (cost: $0.0110)&lt;/li&gt;
&lt;li&gt;Gemini Flash: 2,287 → 587 (cost: $0.0002)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Quality:&lt;/strong&gt; Claude's refactor was production-ready. GPT-4o suggested good ideas but with syntax issues. Gemini's suggestion worked but wasn't elegant.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token efficiency win:&lt;/strong&gt; Gemini cost, Claude quality.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Bug Diagnosis
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; Stack trace (15 lines) + error logs (20 lines) + code snippet (40 lines) + attempted fixes tried&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token usage:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Sonnet: 2,856 → 445 (cost: $0.0071)&lt;/li&gt;
&lt;li&gt;GPT-4o: 3,102 → 421 (cost: $0.0127)&lt;/li&gt;
&lt;li&gt;Gemini Flash: 2,934 → 438 (cost: $0.0002)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Quality:&lt;/strong&gt; Claude nailed it immediately. GPT-4o circled around the issue. Gemini flagged the right file but not the root cause.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token efficiency win:&lt;/strong&gt; Gemini cost, Claude accuracy.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Documentation Generation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; 12 functions with JSDoc comments + expected markdown format + examples&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token usage:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Sonnet: 3,445 → 734 (cost: $0.0118)&lt;/li&gt;
&lt;li&gt;GPT-4o: 3,821 → 689 (cost: $0.0182)&lt;/li&gt;
&lt;li&gt;Gemini Flash: 3,567 → 712 (cost: $0.0004)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Quality:&lt;/strong&gt; Claude's docs were complete and well-structured. GPT-4o was good but required minimal cleanup. Gemini's docs were functional but missing details.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token efficiency win:&lt;/strong&gt; Gemini cost, Claude completeness.&lt;/p&gt;




&lt;h2&gt;
  
  
  The 3 Things I Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Cost-per-task != best value.&lt;/strong&gt; Gemini Flash is comically cheap (~90% less than GPT-4o), but you're paying for what you get. When I needed high-stakes work (code review, bug diagnosis), Claude was worth the extra cents because I didn't have to iterate. For throwaway tasks (generating examples, formatting), Gemini's cost made its mediocrity acceptable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Token count is not predictive of quality.&lt;/strong&gt; All three models produced similar token counts for the same input, but output quality varied wildly. GPT-4o consistently used more tokens and wasn't proportionally better. Claude packed useful signal into fewer tokens. This matters: if you're optimizing for cost alone, you'll pick the wrong model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Real-world testing beats benchmarks.&lt;/strong&gt; The model rankings flip depending on what you're actually doing. For documentation, Claude wins. For budget validation of a throwaway check, Gemini wins. Generic "fastest model" articles don't capture this. You need to test your actual tasks.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Benchmark Yours
&lt;/h2&gt;

&lt;p&gt;Here's the thing: this comparison is data, not law. Your tasks might weight differently. Let me show you how I tested this using PromptFuel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install PromptFuel (if you haven't)&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; promptfuel

&lt;span class="c"&gt;# Create a test file with your prompt&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; test-prompt.txt &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
[your prompt here]
&lt;/span&gt;&lt;span class="no"&gt;EOF

&lt;/span&gt;&lt;span class="c"&gt;# Count tokens across models&lt;/span&gt;
pf count test-prompt.txt &lt;span class="nt"&gt;--model&lt;/span&gt; claude-3-5-sonnet
pf count test-prompt.txt &lt;span class="nt"&gt;--model&lt;/span&gt; gpt-4o
pf count test-prompt.txt &lt;span class="nt"&gt;--model&lt;/span&gt; gemini-2.0-flash

&lt;span class="c"&gt;# Compare costs&lt;/span&gt;
pf count test-prompt.txt &lt;span class="nt"&gt;--compare&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;--compare&lt;/code&gt; flag gives you a cost matrix. Takes 30 seconds. Beats guessing.&lt;/p&gt;

&lt;p&gt;The real insight: &lt;strong&gt;run this for your specific use cases.&lt;/strong&gt; A document summarizer might favor Claude. A high-throughput classification pipeline might favor Gemini. The only way to know is to test.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Optimization
&lt;/h2&gt;

&lt;p&gt;After picking your model, there's still money left on the table. Here's a before/after from actual PromptFuel code:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before (unoptimized prompt):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are an expert code reviewer. Review the following code for quality, security, 
and performance issues. Check for common bugs, suggest improvements, and rate the 
code from 1-10. Consider edge cases, error handling, and best practices. Be thorough 
and detailed in your feedback.

[400 tokens of instructions]
[200 tokens of examples]
[150 tokens of code to review]
Total: ~750 input tokens
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After (optimized with PromptFuel):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Review code for quality, security, performance. Rate 1-10.

[Stripped redundant instructions]
[Examples reduced to 1 exemplar instead of 3]
[Code reformatted to remove whitespace]
Total: ~420 input tokens
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cost saved: ~$0.0012 per review on Claude. Run that 100 times a day, and you're saving $0.12/day, $36/year. Small? Yes. Multiplied by 50 internal tools? Now you're talking real money.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Honest Take
&lt;/h2&gt;

&lt;p&gt;Pick the model that gives you the output you need, then optimize the prompt. Stop optimizing for the wrong metric. Benchmarks are fun, but production bills are real.&lt;/p&gt;

&lt;p&gt;If you're running this analysis for your own stuff, PromptFuel makes it stupidly easy. It's free, no API keys needed, runs locally. Just &lt;code&gt;npm install -g promptfuel&lt;/code&gt; and compare. If you want the actual numbers from your prompts, run the test. Don't inherit my data — build your own.&lt;/p&gt;

&lt;p&gt;What's your highest-volume LLM task? Test it. You might be surprised which model wins.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; #ai #tutorial #javascript #optimization&lt;/p&gt;

</description>
      <category>ai</category>
      <category>tutorial</category>
      <category>javascript</category>
      <category>optimization</category>
    </item>
  </channel>
</rss>
