<?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: J. Gravelle</title>
    <description>The latest articles on DEV Community by J. Gravelle (@jgravelle).</description>
    <link>https://dev.to/jgravelle</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3815404%2F5c973ed1-5fef-4135-b089-56d7dbd03d4d.jpg</url>
      <title>DEV Community: J. Gravelle</title>
      <link>https://dev.to/jgravelle</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jgravelle"/>
    <language>en</language>
    <item>
      <title>The real cost is not "AI"</title>
      <dc:creator>J. Gravelle</dc:creator>
      <pubDate>Thu, 30 Jul 2026 13:16:10 +0000</pubDate>
      <link>https://dev.to/jgravelle/the-real-cost-is-not-ai-4ff3</link>
      <guid>https://dev.to/jgravelle/the-real-cost-is-not-ai-4ff3</guid>
      <description>&lt;h2&gt;
  
  
  Stop Paying for Tools Your AI Isn't Using
&lt;/h2&gt;

&lt;p&gt;Three recent results point at the same costly habit:&lt;/p&gt;

&lt;p&gt;Anthropic reports an &lt;strong&gt;85% token reduction&lt;/strong&gt; from its &lt;a href="https://www.anthropic.com/engineering/advanced-tool-use" rel="noopener noreferrer"&gt;Tool Search Tool&lt;/a&gt;, which discovers tools on demand while keeping the full library reachable.&lt;/p&gt;

&lt;p&gt;An &lt;a href="https://arxiv.org/abs/2607.15593" rel="noopener noreferrer"&gt;arXiv paper&lt;/a&gt; shows &lt;strong&gt;8.9x faster tool selection&lt;/strong&gt; and &lt;strong&gt;23.8x lower token usage&lt;/strong&gt; by loading tools on demand instead of dumping every schema into context, at a scale past 3,000 tools.&lt;/p&gt;

&lt;p&gt;A &lt;a href="https://arxiv.org/abs/2604.08075" rel="noopener noreferrer"&gt;second paper&lt;/a&gt; reports &lt;strong&gt;31 to 42% fewer GPU-hours&lt;/strong&gt; simply by routing on estimated total token budget.&lt;/p&gt;

&lt;p&gt;Different layers. Same diagnosis: &lt;strong&gt;you are still paying a flat rate for capacity the current turn does not need.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That diagnosis is now consensus. What is still rare, and far more useful to a manager, is a number you can generate yourself, on your own install, with one command.&lt;/p&gt;

&lt;h3&gt;
  
  
  The real cost is not "AI." It is idle schema.
&lt;/h3&gt;

&lt;p&gt;An MCP host that serializes every tool's schema into context on every turn creates two separate bills:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A fixed per-turn token tax for tools you did not call.&lt;/li&gt;
&lt;li&gt;Dispatch dilution: the model must choose correctly from a larger and larger menu.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Retrieval-based loading attacks both. Keep a tiny resident surface. Describe the catalog only when asked. Dispatch by name.&lt;/p&gt;

&lt;h3&gt;
  
  
  What we actually shipped
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;21 June 2026 (v1.108.66)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A three-tool front door in front of the entire catalog:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;order(action, args)&lt;/code&gt;: dispatch any catalog action by name&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;menu(query?)&lt;/code&gt;: search and browse the catalog as compact rows&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;route(task, ...)&lt;/code&gt;: map natural language to the best action (and optionally execute it)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No capability removed. Every action remains one call away.&lt;/p&gt;

&lt;p&gt;Safety boundary: &lt;code&gt;order&lt;/code&gt; is read-only at the edge. State-changing or file-write actions require an explicit flag or are refused outright.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;9 July 2026 (v1.108.115)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The collapsed surface became the default for brand-new installs. Existing installs keep their previous surface, enforced by construction rather than by hope.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;21 July 2026 (v1.108.154)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The part that actually matters for cost conversations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jcodemunch-mcp surface
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read-only. Instant. No session required. It reports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;visible tools vs. full catalog&lt;/li&gt;
&lt;li&gt;estimated schema tokens for the active surface&lt;/li&gt;
&lt;li&gt;tokens avoided&lt;/li&gt;
&lt;li&gt;the heaviest schemas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One real install (v1.108.199, measured today):&lt;br&gt;
6 of 94 tools resident, &lt;strong&gt;1,038 of 25,801 estimated schema tokens&lt;/strong&gt;, &lt;strong&gt;24,763 avoided&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That measures resident schema cost only, so it is not comparable to the 85% or the 23.8x above, which measure total token usage. Compare it to your own &lt;code&gt;full&lt;/code&gt; run instead.&lt;/p&gt;

&lt;p&gt;That is not a paper number. It is the number that appears on &lt;em&gt;your&lt;/em&gt; machine when &lt;em&gt;you&lt;/em&gt; run the command.&lt;/p&gt;
&lt;h3&gt;
  
  
  Two different meters, deliberately
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;surface&lt;/code&gt; is an advisory receipt. It uses a bytes/4 estimate so it stays instant and dependency-free.&lt;/p&gt;

&lt;p&gt;The CI schema-budget gate is a different instrument: tiktoken on a frozen baseline with a 5% drift tolerance. Its job is to stop schema bloat from shipping, not to inform a human.&lt;/p&gt;

&lt;p&gt;They will never match digit-for-digit. That is intentional. A receipt that pretends to be a tokenizer count is worse than one that labels its own estimator and stays cheap.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why this is the interesting number
&lt;/h3&gt;

&lt;p&gt;An 85% figure in a blog post is something you accept.&lt;/p&gt;

&lt;p&gt;A figure generated on your own repo, your own config, and your own tool surface is something you can take into a budget meeting.&lt;/p&gt;

&lt;p&gt;The general discipline is simple: if you measure one side of a comparison live and leave the other side as a constant in documentation, the comparison rots, usually in your favor. Nobody audits a flattering constant.&lt;/p&gt;

&lt;p&gt;We fixed our own README the same way. Absolute numbers went stale as the catalog grew; the multiple happened to survive. The line now names the version, states that bytes/4 is an estimate, and points at the command instead of a bare digit.&lt;/p&gt;

&lt;p&gt;A constant in prose has no way to notice it is wrong.&lt;/p&gt;

&lt;p&gt;A command re-derives itself every time someone runs it.&lt;/p&gt;
&lt;h3&gt;
  
  
  The broader pattern
&lt;/h3&gt;

&lt;p&gt;Retrieval shrinks what you load &lt;em&gt;to answer&lt;/em&gt; a question.&lt;/p&gt;

&lt;p&gt;The front door shrinks what you pay &lt;em&gt;before you have asked one&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The field is converging on the second lever. That is progress.&lt;/p&gt;

&lt;p&gt;What should converge next is shipping the meter alongside the optimization.&lt;/p&gt;

&lt;p&gt;If your tool-loading change saves 85%, put a command in the package that tells the next person what it actually saved on &lt;em&gt;their&lt;/em&gt; install.&lt;/p&gt;

&lt;p&gt;They will believe that number, because they generated it.&lt;/p&gt;

&lt;p&gt;Run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jcodemunch-mcp surface
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The interesting number is no longer ours...&lt;/p&gt;

&lt;p&gt;-jjg&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>mcp</category>
      <category>tooling</category>
    </item>
    <item>
      <title>The Harness Effect...</title>
      <dc:creator>J. Gravelle</dc:creator>
      <pubDate>Wed, 22 Jul 2026 13:44:38 +0000</pubDate>
      <link>https://dev.to/jgravelle/the-harness-effect-3aaa</link>
      <guid>https://dev.to/jgravelle/the-harness-effect-3aaa</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;...a controlled study just showed 41% of agent cost is design, not model&lt;/strong&gt;
&lt;/h2&gt;




&lt;p&gt;Thesis: arXiv 2607.06906 held models and tasks constant, varied only the harness, and found 38% fewer tokens and 41% lower blended cost. The post walks the three harness levers the paper implicates: retrieval strategy, tool-surface size, prefix stability, and shows each is independently measurable, and demonstrates per-session instrumentation for measuring your own.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The experiment: 22 tasks, six models, harness-only variation, 38%/41% at level quality. Why "held constant" matters; this isn't a vendor benchmark.&lt;/li&gt;
&lt;li&gt;Lever 1, retrieval: full-file reads vs grounded symbolic retrieval — the 99.6% aggregate (5.12M → 19.4K, 15 task-runs, tiktoken cl100k_base, CI replay-gated), and what varies by repo shape.&lt;/li&gt;
&lt;li&gt;Lever 2, tool surface: companion paper arXiv 2607.15593 on tool-surface bloat; our measurement of 93 resident schemas ≈21.6K tokens/turn vs a 6-tool on-demand front door ≈0.9K (dated CHANGELOG receipt).&lt;/li&gt;
&lt;li&gt;Lever 3, prefix stability: arXiv 2607.15516 (51.7% cost reduction at three reuses on a 94K-token prefix); our deterministic-emission work and the honest part — we measured 0.139 against a 0.30 threshold and held a feature because the problem was small.&lt;/li&gt;
&lt;li&gt;Measuring yourself: token yield rate (credited to FinOps Foundation), the session yield block, advisory budgets, the tool-surface receipt — shipped July 19 and 21, all three servers.&lt;/li&gt;
&lt;li&gt;Close: agent cost is a distribution (per McKinsey) and the harness sets the distribution. Instrument first, optimize second.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;They're preaching to our well-established choir of over 60,000 developers worldwide.  And I'd strongly urge everybody else to pick up a hymnal...&lt;/p&gt;

&lt;p&gt;-jjg&lt;br&gt;
&lt;a href="https://jcodemunch.com" rel="noopener noreferrer"&gt;https://jcodemunch.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>machinelearning</category>
      <category>programming</category>
    </item>
    <item>
      <title>How a retrieval tool can know when it's wrong</title>
      <dc:creator>J. Gravelle</dc:creator>
      <pubDate>Sat, 18 Jul 2026 19:14:12 +0000</pubDate>
      <link>https://dev.to/jgravelle/how-a-retrieval-tool-can-know-when-its-wrong-20eh</link>
      <guid>https://dev.to/jgravelle/how-a-retrieval-tool-can-know-when-its-wrong-20eh</guid>
      <description>&lt;p&gt;Most code-retrieval tools have exactly one voice: confident. You ask, they return their top-k, and the agent on the other end has to guess whether to trust it. That guess fails worst in one specific case: the empty result.&lt;/p&gt;

&lt;p&gt;An empty search result is ambiguous. It can mean &lt;em&gt;the thing doesn't exist&lt;/em&gt;, or it can mean &lt;em&gt;the index couldn't see it&lt;/em&gt;. Those are wildly different facts, and an agent that treats every empty result as "doesn't exist" will confidently hallucinate the negative. "There's no retry logic in this codebase" is a strong claim to make off a search that ran against a half-built index.&lt;/p&gt;

&lt;p&gt;We think retrieval responses should carry their own trust signals, machine-readable, so the agent can gate its next action on data instead of vibes. Here's the contract jCodeMunch ships, offered as a shape we'd like to see more of the ecosystem adopt.&lt;/p&gt;

&lt;h2&gt;
  
  
  The four-state verdict
&lt;/h2&gt;

&lt;p&gt;Every retrieval response carries a verdict:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;ok&lt;/code&gt;&lt;/strong&gt;: confident matches returned.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;low_confidence&lt;/code&gt;&lt;/strong&gt;: matches exist but score below the confidence threshold. Verify before relying on them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;absent&lt;/code&gt;&lt;/strong&gt;: the corpus was genuinely scanned and the answer isn't there. The verdict carries the scan counts (how many symbols and files were actually examined), so "absent" is a claim with evidence, not a shrug.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;degraded&lt;/code&gt;&lt;/strong&gt;: the index itself is impaired (stale, partial, or mid-rebuild). A missing or thin result may be truncation, not absence. Don't conclude anything from silence in this state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The absent-versus-degraded distinction is the whole point. "Absent" is a positive claim: we looked, here's how much we looked at, it isn't there. "Degraded" is the index admitting it can't be trusted right now. Collapsing those two into one empty list is lying by omission, and it's what most retrieval surfaces do today.&lt;/p&gt;

&lt;p&gt;For an agent, the practical difference is enormous. On &lt;code&gt;absent&lt;/code&gt;, stop re-querying; the code provably isn't indexed there. On &lt;code&gt;degraded&lt;/code&gt;, don't conclude anything; refresh the index or fall back to a raw read. Without the distinction, agents burn tokens re-asking questions the index already answered, or worse, they build plans on a negative that was never proven.&lt;/p&gt;

&lt;h2&gt;
  
  
  Signal two: calibrated confidence
&lt;/h2&gt;

&lt;p&gt;Verdicts cover the empty case. For non-empty results, every response carries a 0 to 1 confidence score composed from measurable components: the top-1 versus top-2 score gap (is the winner dominant or a coin flip?), absolute top-1 strength, whether an exact identity match is present, and index freshness.&lt;/p&gt;

&lt;p&gt;One number, gateable. An agent can decide "above 0.8, use it; below, fetch the source and check" without parsing prose.&lt;/p&gt;

&lt;h2&gt;
  
  
  Signal three: per-symbol freshness
&lt;/h2&gt;

&lt;p&gt;Every result entry is stamped &lt;code&gt;fresh&lt;/code&gt;, &lt;code&gt;edited_uncommitted&lt;/code&gt;, or &lt;code&gt;stale_index&lt;/code&gt;, derived from comparing the index's recorded git HEAD against the working tree's actual HEAD plus per-file mtime checks. The index doesn't pretend the world stopped at indexing time. It tells you, per symbol, whether what it's showing you still matches the bytes on disk.&lt;/p&gt;

&lt;h2&gt;
  
  
  The contract is machine-checkable
&lt;/h2&gt;

&lt;p&gt;None of this is prose in a README. The verdict contract is published as a JSON Schema (&lt;code&gt;schemas/retrieval-verdict.schema.json&lt;/code&gt; in the repo), alongside schemas for the confidence provenance and the ranked-context response shape. A CI pipeline, yours and not just ours, can validate live responses against it mechanically. If a response ever ships without the honesty fields, that's a schema violation, not a style regression.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why bother
&lt;/h2&gt;

&lt;p&gt;Retrieval quality gets all the benchmark attention. Retrieval &lt;em&gt;honesty&lt;/em&gt; gets almost none, and it's the thing agents actually break on. A tool that's right 95% of the time but can't tell you which 5% it's unsure about forces the agent to treat every answer with the same suspicion, which means re-verifying everything, which means the retrieval tool saved you nothing.&lt;/p&gt;

&lt;p&gt;Three honest signals (verdict, confidence, freshness) let the agent spend verification effort only where the tool itself flagged doubt. That's the trade we think the whole ecosystem should be making, and the schema is there for anyone who wants to make it.&lt;/p&gt;

&lt;p&gt;The full mechanics are in Chapter 1 of the technical manual: &lt;a href="https://github.com/jgravelle/jcodemunch-mcp/blob/main/UNDER_THE_HOOD.md" rel="noopener noreferrer"&gt;https://github.com/jgravelle/jcodemunch-mcp/blob/main/UNDER_THE_HOOD.md&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If a claim in this post doesn't match the source, that's a bug in the post. File an issue and I'll fix it.&lt;/p&gt;

&lt;p&gt;-jjg&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>devtools</category>
      <category>agents</category>
    </item>
    <item>
      <title>About that 'your 997 says rejected but not why' problem...</title>
      <dc:creator>J. Gravelle</dc:creator>
      <pubDate>Tue, 14 Jul 2026 18:35:52 +0000</pubDate>
      <link>https://dev.to/jgravelle/about-that-your-997-says-rejected-but-not-why-problem-1ab3</link>
      <guid>https://dev.to/jgravelle/about-that-your-997-says-rejected-but-not-why-problem-1ab3</guid>
      <description>&lt;p&gt;Somebody on Reddit posted about 997s that just say &lt;code&gt;AK5*R*5&lt;/code&gt; — &lt;em&gt;one or more segments in error&lt;/em&gt; — no &lt;code&gt;AK3&lt;/code&gt;, no &lt;code&gt;AK4&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Preach.&lt;/p&gt;

&lt;p&gt;That's the problem this free doohickey* is for: &lt;strong&gt;&lt;a href="https://rejectdecoder.com" rel="noopener noreferrer"&gt;rejectdecoder.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;sup&gt;*If you'd prefer a "gizmo", I can make that happen.&lt;/sup&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;Paste the rejection (997, 999, 824, TA1) plus the original bounced document. It parses both &lt;strong&gt;locally in your browser&lt;/strong&gt; and cross-audits them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;control number agreement&lt;/li&gt;
&lt;li&gt;segment counts&lt;/li&gt;
&lt;li&gt;envelope consistency&lt;/li&gt;
&lt;li&gt;code validity&lt;/li&gt;
&lt;li&gt;required segments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It then quotes the exact segment byte-for-byte and ranks the likely causes for anything it finds. If it finds nothing, it says the answer isn't in the docs and tells you to escalate to your partner with your control numbers — which beats pulling a diagnosis out of my... AIs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the AI does (and doesn't) fit
&lt;/h2&gt;

&lt;p&gt;I know how and appreciate WHY "AI-powered EDI" is sneered at. So the audits here are deterministic parser code, not a model. The AI only writes the plain-English narration of facts the parser already verified, every card says so, and if the narration fails you still get the full audit results. No hallucinations or guesswork.&lt;/p&gt;

&lt;h2&gt;
  
  
  Privacy
&lt;/h2&gt;

&lt;p&gt;Parsing runs entirely in-browser (the real Python parser, compiled to WebAssembly via Pyodide) and even works with the WiFi off. If you use narration, only a masked summary you preview first ever leaves the page. Don't take my word for it — check your network tab.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Free. No signup for the examples or the deterministic audits; narration is a handful of decodes a month with just an email.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Built it solo from an in-house tool of mine, so it's young AND kinda old. Please tell me where it's wrong. Walmart's rejection quirks are encoded so far. Whose partner nonsense should be next...?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;-jjg&lt;/em&gt;&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>webassembly</category>
      <category>python</category>
      <category>webdev</category>
    </item>
    <item>
      <title>You Don't Need an LLM to Route Agent Context: Regex Beats Classifiers by 45 Points</title>
      <dc:creator>J. Gravelle</dc:creator>
      <pubDate>Wed, 08 Jul 2026 18:35:19 +0000</pubDate>
      <link>https://dev.to/jgravelle/you-dont-need-an-llm-to-route-agent-context-regex-beats-classifiers-by-45-points-1hb6</link>
      <guid>https://dev.to/jgravelle/you-dont-need-an-llm-to-route-agent-context-regex-beats-classifiers-by-45-points-1hb6</guid>
      <description>&lt;p&gt;LLM agents burn a ridiculous number of tokens on redundancy: opening the same files again and again, trying a patch, failing, then wandering back through the repo like they’ve never seen it before.&lt;/p&gt;

&lt;p&gt;A July 2026 paper, &lt;em&gt;ContextSniper: AntTrail's Token-Efficient Code Memory for Repository-Level Program Repair&lt;/em&gt;, puts real numbers behind that waste. In repository-level repair, agents keep dragging in irrelevant code and logs. ContextSniper tackles that with a context layer built around tiered memory and an &lt;strong&gt;intention-aware context gate&lt;/strong&gt; that filters low-value regions before they ever reach the model.&lt;/p&gt;

&lt;p&gt;That gate alone cut tokens by 51.5% on one host agent and 38.9% on Claude Code, while submitted-resolution rates stayed basically in the same neighborhood.&lt;/p&gt;

&lt;p&gt;The gate is the interesting part, because it is not tied to that paper’s exact system. It is a more general idea, and it is starting to show up across agent architectures.&lt;/p&gt;

&lt;p&gt;At heart, the gate is just a classifier. Given a request, it has to decide what kind of retrieval will answer the question cheapest: symbol lookup, semantic search, graph impact, mutation prep, or something else.&lt;/p&gt;

&lt;p&gt;That leads to the practical question the paper does not really answer:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Do you need another LLM call just to decide what context to retrieve?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We tested that directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Five ways agents get code into context
&lt;/h2&gt;

&lt;p&gt;Before you can gate anything, you need a retrieval strategy. Most current systems fall into one of five rough families:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Grounded read-only retrieval:&lt;/strong&gt; parse the code and return exact symbol source by name. Byte-precise, no synthesis.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Graph code intelligence:&lt;/strong&gt; model calls, imports, entities, and dependencies as a graph, then traverse it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embedding / RAG search:&lt;/strong&gt; use vector similarity over chunks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Whole-repo packers:&lt;/strong&gt; compress or dump the repo into the context window.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mutate / execute runtimes:&lt;/strong&gt; retrieve context, then modify or run code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these is magic. Graphs are great for relationships, but they can drift away from source. RAG is useful, but fuzzy by design. Packers are simple, but expensive. Mutation runtimes are powerful, but they widen the blast radius.&lt;/p&gt;

&lt;p&gt;The important point is that every approach still has to answer the same question:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What should I fetch for this request?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That decision is the gate.&lt;/p&gt;

&lt;h2&gt;
  
  
  The gate is where the real leverage is
&lt;/h2&gt;

&lt;p&gt;An intention-aware gate looks at a request like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“where is &lt;code&gt;parse_config&lt;/code&gt; defined”&lt;/li&gt;
&lt;li&gt;“how does caching work here”&lt;/li&gt;
&lt;li&gt;“what breaks if I rename this”&lt;/li&gt;
&lt;li&gt;“change the timeout to 60s”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then it chooses the cheapest retrieval path that is likely to work.&lt;/p&gt;

&lt;p&gt;That might be a symbol lookup. It might be semantic search. It might be a graph-impact query. It might be mutation prep.&lt;/p&gt;

&lt;p&gt;ContextSniper uses a traceback / behavioral / stateful intent split, which is a useful framing. But it leaves an obvious engineering question for anyone building this kind of system:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;How heavy does the gate actually need to be?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The default instinct is to reach for an LLM router, because “intent” sounds like a language-understanding problem.&lt;/p&gt;

&lt;p&gt;We wanted to know whether that was true.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;We used 140 hand-authored requests, balanced across seven dispatch classes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;symbol lookup&lt;/li&gt;
&lt;li&gt;text search&lt;/li&gt;
&lt;li&gt;semantic&lt;/li&gt;
&lt;li&gt;graph impact&lt;/li&gt;
&lt;li&gt;structure&lt;/li&gt;
&lt;li&gt;stateful&lt;/li&gt;
&lt;li&gt;mutate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The label space borrows from ContextSniper’s intent split. We ran five-fold stratified cross-validation and compared three cheap routing tiers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;heuristic:&lt;/strong&gt; about 40 lines of regex over the request text&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;centroid:&lt;/strong&gt; TF-IDF with nearest class mean&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;logreg:&lt;/strong&gt; TF-IDF with a linear classifier&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The result
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tier&lt;/th&gt;
&lt;th&gt;What&lt;/th&gt;
&lt;th&gt;Accuracy&lt;/th&gt;
&lt;th&gt;Macro-F1&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;heuristic&lt;/td&gt;
&lt;td&gt;~40 lines of regex&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;94.3%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.945&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;centroid&lt;/td&gt;
&lt;td&gt;TF-IDF nearest-class&lt;/td&gt;
&lt;td&gt;47.9%&lt;/td&gt;
&lt;td&gt;0.474&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;logreg&lt;/td&gt;
&lt;td&gt;TF-IDF linear&lt;/td&gt;
&lt;td&gt;48.6%&lt;/td&gt;
&lt;td&gt;0.484&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The regex tier won by about 45 points.&lt;/p&gt;

&lt;p&gt;The two learned models were not terrible for a seven-class problem, but they were nowhere close. Same corpus, same folds, same labels, and the dumb little ruleset walked off with the trophy.&lt;/p&gt;

&lt;p&gt;That was surprising enough that we dug into why.&lt;/p&gt;

&lt;h2&gt;
  
  
  Intent lives in shape, not word frequency
&lt;/h2&gt;

&lt;p&gt;Bag-of-words models care about which words appear and how often. But for these requests, intent usually lives somewhere else. It lives in the shape of the request.&lt;/p&gt;

&lt;p&gt;“Where is &lt;code&gt;X&lt;/code&gt; defined” and “how does caching work” do not share much useful vocabulary, but both are almost embarrassingly easy to classify from structure alone.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;camelCase&lt;/code&gt; or &lt;code&gt;snake_case&lt;/code&gt; token usually means symbol lookup.&lt;/p&gt;

&lt;p&gt;A leading “how does” or “why” usually means behavioral or semantic exploration.&lt;/p&gt;

&lt;p&gt;“What breaks if I” usually means impact analysis.&lt;/p&gt;

&lt;p&gt;“Change,” “rename,” or “set ... to” usually means mutation.&lt;/p&gt;

&lt;p&gt;A quoted literal or bare number often means text search.&lt;/p&gt;

&lt;p&gt;Regex sees those shapes directly.&lt;/p&gt;

&lt;p&gt;TF-IDF mostly throws them away, then gets punished again by the tiny dataset. With roughly 16 examples per class, a sparse linear model does not have much signal left to recover.&lt;/p&gt;

&lt;p&gt;In this experiment, the cheap learned tier was not merely unnecessary. It was worse than the rules.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 3% that fights back
&lt;/h2&gt;

&lt;p&gt;Four of the 140 requests resisted both cheap tiers:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Example Request&lt;/th&gt;
&lt;th&gt;Why it resists cheap classification&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;what does the parse method look like&lt;/td&gt;
&lt;td&gt;symbol lookup, but no definitional keyword&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;find where the timeout value 30000 appears&lt;/td&gt;
&lt;td&gt;text search phrased like a location query&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;show me how caching is implemented&lt;/td&gt;
&lt;td&gt;semantic vs symbol, genuinely ambiguous&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;what modules depend on the core package&lt;/td&gt;
&lt;td&gt;graph question that reads structural&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These are not really rule failures. They are ambiguity.&lt;/p&gt;

&lt;p&gt;And the fix for ambiguity is not always “ask a bigger model.” Often, the fix is to probe reality.&lt;/p&gt;

&lt;p&gt;Try the cheapest grounded lookup first. If it misses, fall back to semantic search. That resolves the uncertainty by checking the code, not by paying a language model to make a better guess.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to build
&lt;/h2&gt;

&lt;p&gt;For an intention-aware gate, the order should be:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Start with regex.&lt;/strong&gt; It handles most traffic, costs nothing, behaves deterministically, and never rate-limits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add probe-and-fallback for the ambiguous cases.&lt;/strong&gt; When a request could mean two things, cheaply test the first interpretation before escalating.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use a model call only for what survives both.&lt;/strong&gt; In our corpus, that was about 3% of requests, and even those had cheaper ways out.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The expensive tier should be the last resort, not the front door.&lt;/p&gt;

&lt;p&gt;That is the opposite of the usual reflex, which is to reach for an LLM router because the problem sounds like “understanding.” In practice, a lot of the signal is sitting right there in the punctuation, casing, verbs, and shape of the request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest caveats
&lt;/h2&gt;

&lt;p&gt;Two points that really matter:&lt;/p&gt;

&lt;p&gt;First, our corpus and rules share an author. So 94.3% is an in-distribution number. It proves that hand-written rules can separate hand-written requests, which is not exactly a thunderclap from Mount Science.&lt;/p&gt;

&lt;p&gt;The number is less important than the shape of the result. Real validation needs real request logs. I would happily rerun this on a public trace.&lt;/p&gt;

&lt;p&gt;Second, ContextSniper is convergent evidence, not an endorsement of any specific tool. It is a separate group arriving at the same architecture from the repair-agent direction: tiered memory plus an intent gate, large token savings, and resolution held roughly flat.&lt;/p&gt;

&lt;p&gt;To be precise about “roughly,” their official validation reports 24.0% of issues resolved with the gate versus 26.0% for the baseline, which they describe as comparable while also noting a validation-error imbalance.&lt;/p&gt;

&lt;p&gt;The important signal is that two independent lines of work are landing in the same place: context gates matter. The exact accuracy of one regex tier is not the point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this leaves the taxonomy
&lt;/h2&gt;

&lt;p&gt;The gate sits above whatever retrieval family you use.&lt;/p&gt;

&lt;p&gt;In our stack, it routes into a grounded read-only retriever, &lt;a href="https://github.com/jgravelle/jcodemunch-mcp" rel="noopener noreferrer"&gt;jCodeMunch&lt;/a&gt;, because byte-exact symbol source is often the cheapest correct answer to the most common kind of request.&lt;/p&gt;

&lt;p&gt;But the routing lesson is not specific to jCodeMunch. It applies whether you retrieve by symbol, graph, vector, or whole-repo packing.&lt;/p&gt;

&lt;p&gt;The thing deciding what to retrieve should be cheap first, deterministic second, shape-aware third, and “smart” only when it has no cheaper option left.&lt;/p&gt;

&lt;p&gt;For the full map of the five families and where different tools fit, there is a running &lt;a href="https://jcodemunch.com/field-guide.php" rel="noopener noreferrer"&gt;field guide to code-context tools&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Links:&lt;/strong&gt; &lt;a href="https://arxiv.org/abs/2607.01916" rel="noopener noreferrer"&gt;ContextSniper (arXiv 2607.01916)&lt;/a&gt; · &lt;a href="https://jcodemunch.com/field-guide.php" rel="noopener noreferrer"&gt;field guide to code-context tools&lt;/a&gt; · &lt;a href="https://github.com/jgravelle/jcodemunch-mcp" rel="noopener noreferrer"&gt;jCodeMunch&lt;/a&gt;&lt;/p&gt;

</description>
      <category>tokenmaxxing</category>
      <category>modelmaxxing</category>
      <category>llm</category>
      <category>contextsniper</category>
    </item>
    <item>
      <title>They Spent $81,267 By Accident...</title>
      <dc:creator>J. Gravelle</dc:creator>
      <pubDate>Mon, 29 Jun 2026 15:43:43 +0000</pubDate>
      <link>https://dev.to/jgravelle/they-spent-81267-by-accident-3d6b</link>
      <guid>https://dev.to/jgravelle/they-spent-81267-by-accident-3d6b</guid>
      <description>&lt;h2&gt;
  
  
  ...and I Spent $1.39 On Purpose
&lt;/h2&gt;




&lt;p&gt;Last week, fintech startup Slash told its whole company to lean into AI coding. One employee took that note personally, sat down with Claude, and built a video game.&lt;/p&gt;

&lt;p&gt;Then the bill showed up: &lt;strong&gt;$81,267&lt;/strong&gt;. In one week. On the company card.&lt;/p&gt;

&lt;p&gt;The game is called Brainrot Shooter. It's a bare-bones, blocky, Minecraft-looking first-person shooter where you run around blasting characters named after viral memes (Skibidi Toilet, Tung Tung Tung Sahur, the whole brainrot pantheon). Slash handled the receipt the only sane way: they posted it to the internet and begged people to play the game so they could write it off as a marketing expense. It went viral. The dumb little game actually found an audience.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fya2p4ywi3dz17ol66n83.png" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fya2p4ywi3dz17ol66n83.png" alt="$80,000 Brainrot game" width="800" height="671"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;The employee summed it up himself: "This is actually insane, am I going to become a case study for how AI spend can get out of control."&lt;/p&gt;

&lt;p&gt;Yes. You are. And this is the case study. But not the one you think.&lt;/p&gt;




&lt;h2&gt;
  
  
  Everybody blamed the wrong thing
&lt;/h2&gt;

&lt;p&gt;The internet's takeaway was "see, AI coding is a money pit." That's the lazy read, and it's wrong. The model didn't cost him eighty grand. The way he used it did.&lt;/p&gt;

&lt;p&gt;Here is the part nobody on X bothered to explain.&lt;/p&gt;

&lt;p&gt;A coding agent is stateless. The model has no memory between turns. So every single time you hit send, the harness re-sends the context it needs: your system prompt, the conversation so far, and the file contents the model is supposed to look at. The model reads all of it, fresh, every turn. You pay for all of it, fresh, every turn.&lt;/p&gt;

&lt;p&gt;Now watch what happens over a full day of active development. Your codebase grows. Your conversation grows. The agent keeps pulling large files into context so it can "look at the whole project and change this one thing." Every one of those turns re-bills everything you already showed it five minutes ago. Do that across hundreds of turns on a swelling codebase and the meter spins like a slot machine that never pays out.&lt;/p&gt;

&lt;p&gt;That is not the AI being expensive. That is you paying to make it re-read the same code a few hundred times.&lt;/p&gt;




&lt;h2&gt;
  
  
  The tell is in the token split
&lt;/h2&gt;

&lt;p&gt;Here's where it gets concrete, and here's the part a developer can actually use.&lt;/p&gt;

&lt;p&gt;Claude Opus 4.8 bills input and output tokens at different rates. As of this writing, straight from Anthropic's own announcement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Input: $5 per million tokens&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Output: $25 per million tokens&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Output is five times pricier per token. So your gut says output is where the money goes. In agentic coding, that's backwards. Output tokens are what the model writes, and a model can only write so fast. Input tokens are what the model reads, and there is no ceiling on how many times you can make it re-read the same files. Input is cheaper per token and ruinous in volume, because volume is the thing that compounds turn over turn.&lt;/p&gt;

&lt;p&gt;So when a coding bill goes nuclear, it's almost always input-dominated. I don't have the Slash employee's dashboard, so I won't pretend to quote his exact split. But a five-figure bill from a single day of iterative development is the unmistakable signature of context reloading: the same big files, read again and again, hundreds of turns deep. That is the mechanism. That is what burned the card.&lt;/p&gt;

&lt;p&gt;Which gave me an idea for a test.&lt;/p&gt;




&lt;h2&gt;
  
  
  Same game. One shot. On purpose.
&lt;/h2&gt;

&lt;p&gt;I rebuilt Brainrot Shooter from scratch (mine's called jBrainRot, naturally). Same premise, same blocky world, same meme enemies waddling at you while a combo counter climbs. The difference was in how I asked.&lt;/p&gt;

&lt;p&gt;Instead of a day-long conversation where the model re-reads a growing codebase on every turn, I wrote &lt;strong&gt;one&lt;/strong&gt; complete, self-contained prompt. A full spec: the tech constraints, the controls, the enemies, the game feel, all of it, up front. One message. One shot. No "now look at the file again and tweak this" loop, because the loop is the leak.&lt;/p&gt;

&lt;p&gt;I also ran &lt;a href="https://jcodemunch.com" rel="noopener noreferrer"&gt;jCodeMunch&lt;/a&gt; in the middle, an MCP tool I built that trims the dead weight out of context before it ever reaches the model. (Full disclosure: that's my product. Use it, don't use it, the principle stands either way.)&lt;/p&gt;

&lt;p&gt;The result was a playable browser game. And here's the receipt:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Input: 11,900 tokens&lt;/strong&gt; = $0.0595&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output: 53,400 tokens&lt;/strong&gt; = $1.335&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Total: $1.39&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Look at that split. It's &lt;strong&gt;output-heavy&lt;/strong&gt;. The model spent its tokens &lt;em&gt;writing the game&lt;/em&gt;, not &lt;em&gt;re-reading the game&lt;/em&gt;. That is the exact inverse of the reloading trap, and it's why the number has a decimal point in front of it instead of five digits.&lt;/p&gt;

&lt;p&gt;His $81,267 versus my $1.39. That's roughly &lt;strong&gt;58,000 to one&lt;/strong&gt;, for the same dumb game.&lt;/p&gt;




&lt;h2&gt;
  
  
  Don't Nick-Up Your Budget
&lt;/h2&gt;

&lt;p&gt;You don't need my tool to avoid this (but it'd really help). You need to stop paying to make the robot re-read. A few rules that actually move the number:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Spec hard, then let it write.&lt;/strong&gt; The single biggest lever is turning a hundred small "look again and tweak" turns into one well-specified turn. Re-reads are the cost. Front-load the thinking so the model writes instead of re-reads. An output-heavy bill is a healthy bill.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Watch your context window, not just your prompt.&lt;/strong&gt; The expensive token is the one you send 300 times without noticing. If your agent is loading huge files every turn, that's your leak. Trim it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Turn on prompt caching.&lt;/strong&gt; Anthropic's prompt caching bills repeated context at cache-read rates, up to 90% cheaper than fresh input. If you're running long sessions without it, you're paying full freight to re-read static files. This alone would have gutted a bill like Nick's.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cap your spend, then watch the meter.&lt;/strong&gt; Set a hard budget limit in your harness before you start, not after the invoice. And put eyes on the live number: something like our free &lt;a href="https://github.com/jgravelle/jmunch-console" rel="noopener noreferrer"&gt;jmunch-console&lt;/a&gt; that not only tracks token usage, savings, and throughput, but also fires threshold alerts so a rogue leak trips a wire instead of surfacing as a five-figure surprise. (Disclosure: also mine. The category is the point.) "I underestimated my own ability" is a beautiful sentence and a terrible budgeting strategy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mind the defaults.&lt;/strong&gt; Opus 4.8 defaults to high effort and bills its thinking tokens at output rates. Great for hard problems, wasteful for trivial ones. Match the effort to the task.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh7tdccx2myo2biib5s37.png" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh7tdccx2myo2biib5s37.png" alt="jMunch-console : token savings" width="799" height="609"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;None of this is exotic. It's just the stuff nobody tells you until your CFO takes your nameplate off the wall.&lt;/p&gt;




&lt;h2&gt;
  
  
  The actual lesson
&lt;/h2&gt;

&lt;p&gt;The viral version of this story is "AI made a guy spend $81,000." The true version is "a guy paid to make a model re-read his code a few hundred times, and nobody had set a limit."&lt;/p&gt;

&lt;p&gt;The model isn't the money pit. Your context window is. Watch that, and the same work that torched a five-figure bill costs you next to nothing...&lt;/p&gt;




&lt;p&gt;*The full one-shot prompt I used (and jBrainRot, the game it built) are free on the repo. More token-efficiency tooling at &lt;a href="https://jcodemunch.com" rel="noopener noreferrer"&gt;jcodemunch.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Your AI's memory is quietly making it worse</title>
      <dc:creator>J. Gravelle</dc:creator>
      <pubDate>Thu, 11 Jun 2026 11:16:16 +0000</pubDate>
      <link>https://dev.to/jgravelle/your-ais-memory-is-quietly-making-it-worse-1n0c</link>
      <guid>https://dev.to/jgravelle/your-ais-memory-is-quietly-making-it-worse-1n0c</guid>
      <description>&lt;h1&gt;
  
  
  ...and your CLAUDE.md is next
&lt;/h1&gt;

&lt;p&gt;On June 10, TechCrunch ran a piece called "How memory tools can make AI models worse." I read it the night it dropped, and the next morning I shipped a fix to one of my MCP servers. So this one's personal.&lt;/p&gt;

&lt;p&gt;Memory systems built to personalize your AI, the ones that remember your preferences so the model feels like it knows you, can make that model less accurate and more sycophantic as the stored context piles up. The research came out of Writer, led by Dan Bikel, and it tested real systems (Mem0 and Zep) under peer review. The feature sold as making your assistant smarter was, in their tests, making it dumber.&lt;/p&gt;

&lt;p&gt;Here's the part most coverage skipped: This isn't a chatbot problem. If you run coding agents with a CLAUDE.md file, a memory MCP, learned routing weights, or any config that accumulates over time, you're exposed to the exact same failure mode. The mechanism doesn't care whether the persistent state lives in a vector store or a markdown file in your repo root.&lt;/p&gt;

&lt;h2&gt;
  
  
  The common thread
&lt;/h2&gt;

&lt;p&gt;In every version of this failure, the cause is the same. You have persistent state with no notion of relevance and no notion of expiry. The system stores something true at the time you stored it, then keeps applying it forever, to everything, whether it fits or not.&lt;/p&gt;

&lt;p&gt;The research has a clean example. Tell the model a user's favorite book is "Station Eleven." Later, ask a question that has nothing to do with reading preferences, and the model reaches for that stored fact anyway and names the book as a bestselling dystopian novel. The anchor leaked into a query it didn't belong in. In their financial-analysis tests it got worse: models with memory enabled started adopting the user's misconceptions instead of running the numbers independently. The memory didn't add knowledge. It added a bias the model felt obligated to honor.&lt;/p&gt;

&lt;p&gt;Once you see the pattern, you start seeing it in your own tooling. Four places, specifically. Here's each one and the shape of the fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem 1: Stale anchors
&lt;/h2&gt;

&lt;p&gt;Learned state goes stale and keeps steering anyway. Tuned weights, cached rankings, accumulated usage stats: if any of them trained on your project as it looked six months ago, they're still nudging behavior toward a codebase that no longer exists. The model isn't wrong about what it learned. It's wrong about &lt;em&gt;when&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The fix is a recency window on anything that learns from a history log. Don't compute proposals from all of time. Compute them from the part of time that still resembles now.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timedelta&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;learn_weights&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;window_days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lifetime&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;lifetime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;                      &lt;span class="c1"&gt;# explicit escape hatch
&lt;/span&gt;        &lt;span class="n"&gt;scoped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;               &lt;span class="c1"&gt;# for true lifetime reads
&lt;/span&gt;    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;cutoff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;window_days&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;scoped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;cutoff&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;compute_proposals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scoped&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The window is the whole point. The &lt;code&gt;lifetime&lt;/code&gt; flag is there because sometimes you really do want the full ledger, and that should be a deliberate choice you can read in the call site, not the silent default. This is the fix I shipped the morning after the article. It was about nine lines.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem 2: Irrelevant anchors and preference leakage
&lt;/h2&gt;

&lt;p&gt;This is the "Station Eleven" failure, generalized. A memory store retrieves candidates by similarity, similarity is loose, and a memory that's vaguely close to your query gets injected into the prompt for a query it has nothing to do with. The model treats it as relevant because you handed it over. So scope the injection.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;gather_memories&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;threshold&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.82&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;keep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;relevance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;threshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;                  &lt;span class="c1"&gt;# not close enough, drop it
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;provenance_ok&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;     &lt;span class="c1"&gt;# where did this come from?
&lt;/span&gt;            &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="n"&gt;keep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;keep&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two gates, not one. Relevance decides whether the memory belongs in &lt;em&gt;this&lt;/em&gt; query, and a provenance check decides whether you trust where it came from in the first place. When a candidate is borderline, leave it out. A missing memory costs you one extra lookup. A wrong anchor costs you correctness, and you won't see the bill until the answer's already wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem 3: Memory-file rot
&lt;/h2&gt;

&lt;p&gt;Your CLAUDE.md, your AGENTS.md, your .cursorrules: these are memory too, just written in markdown instead of embeddings. And they rot. You rename a function and the file still references the old name. You delete a directory and the file still points at the path. You add a rule in March that contradicts a rule from January, and both are still in there. The agent reads all of it as gospel and obeys ghosts.&lt;/p&gt;

&lt;p&gt;The fix is to audit the config against ground truth, meaning the actual code, not the config's memory of the code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;audit_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code_index&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;issues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;referenced_symbols&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;code_index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;symbols&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stale_ref&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;referenced_paths&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;code_index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dead_path&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;issues&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nf"&gt;find_contradictions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;issues&lt;/span&gt;   &lt;span class="c1"&gt;# flag for deletion, don't auto-delete
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every symbol the config names should exist in the index. Every path should resolve. Every rule should be consistent with its neighbors. Anything that fails gets flagged for a human to cut. You'd be surprised how much dead weight a six-month-old agent file is carrying.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem 4: Silent self-modification
&lt;/h2&gt;

&lt;p&gt;This is the one that turns a small error into a spiral. Some systems write their own memory or rewrite their own config without a checkpoint. So the model makes a wrong inference, stores it, reads it back next turn as a fact it "already knows," and builds on it. That loop is how sycophancy snowballs. Nobody ever told it no, so it keeps agreeing with the wrong thing more confidently each round.&lt;/p&gt;

&lt;p&gt;The rule is simple. Suggest, never write.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;propose_memory_update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;proposed&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;diff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;render_diff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;proposed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diff&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;approval_step&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diff&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;       &lt;span class="c1"&gt;# human or supervising agent
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;                &lt;span class="c1"&gt;# rejected, nothing changes
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;proposed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The system can propose whatever it wants. It just can't commit. Show the diff, require an explicit yes, and the snowball never starts because there's always a point where someone can look at the change and say that's not right.&lt;/p&gt;

&lt;h2&gt;
  
  
  The actual fix isn't "turn memory off"
&lt;/h2&gt;

&lt;p&gt;None of this argues for ripping memory out. Memory is useful. A model that remembers your stack and your conventions is a better collaborator than one that re-learns you every session.&lt;/p&gt;

&lt;p&gt;The fix is memory with hygiene. Recency windows so old state expires. Relevance scoping so anchors only fire on the queries they fit. Ground-truth audits so your config can't drift away from your code. Human-in-the-loop writes so errors can't compound unsupervised.&lt;/p&gt;

&lt;p&gt;And underneath all four guards there's one principle. Grounded retrieval beats accumulated recollection. Deriving your context from the source artifact at query time, the live code, the current files, the real index, will beat trusting what you wrote down about that artifact months ago. Recollection rots. The source doesn't.&lt;/p&gt;

&lt;p&gt;You can wire up all four of these guards yourself. The sketches above are most of the shape, and none of them are long.&lt;/p&gt;

&lt;p&gt;Or you can install jCodeMunch, a free MCP server (&lt;code&gt;pip install jcodemunch-mcp&lt;/code&gt;) where this is already the architecture. Retrieval is grounded in a live index of your actual code instead of accumulated memory, weight learning is recency-windowed out of the box, and a built-in &lt;code&gt;audit_agent_config&lt;/code&gt; tool finds the rot in your CLAUDE.md for you. It's here: &lt;a href="https://github.com/jgravelle/jcodemunch-mcp" rel="noopener noreferrer"&gt;https://github.com/jgravelle/jcodemunch-mcp&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>machinelearning</category>
      <category>programming</category>
    </item>
    <item>
      <title>Look What GitLab Invented!</title>
      <dc:creator>J. Gravelle</dc:creator>
      <pubDate>Sun, 31 May 2026 12:38:03 +0000</pubDate>
      <link>https://dev.to/jgravelle/look-what-gitlab-invented-373c</link>
      <guid>https://dev.to/jgravelle/look-what-gitlab-invented-373c</guid>
      <description>&lt;p&gt;The industry just got slapped awake by two numbers it cannot unsee.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://fortune.com/2026/05/26/uber-coo-ai-spending-tokens-claude-code/" rel="noopener noreferrer"&gt;Uber torched its entire 2026 AI coding budget in four months.&lt;/a&gt; Its COO went on record saying he still cannot draw a straight line from all that Claude Code spend to shipping more useful features. "That link is not there yet."&lt;/p&gt;

&lt;p&gt;At the same time, &lt;a href="https://www.tomshardware.com/tech-industry/artificial-intelligence/mystery-company-accidentally-blew-usd500-million-on-claude-in-a-single-month-failed-to-put-usage-limit-on-licenses-for-employees" rel="noopener noreferrer"&gt;an unnamed company accidentally dropped half a billion dollars on Claude&lt;/a&gt; in a single month because nobody put a cap on employee licenses.&lt;/p&gt;

&lt;p&gt;The panic narrative writes itself: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"AI IS TOO EXPENSIVE!"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The diagnosis everyone is missing: most of those tokens were spent forcing models to skim entire files just to find the three functions, classes, or references they actually needed.&lt;/p&gt;

&lt;p&gt;You are not paying for intelligence. You are paying retail, per token, to make the robot read the whole damn book when it only needed one page.&lt;/p&gt;




&lt;h2&gt;
  
  
  GitLab just validated the fix in public
&lt;/h2&gt;

&lt;p&gt;While the budget fires were burning, GitLab was building the same fix in the open. They call it Orbit, their Knowledge Graph. It turns repositories into a structured, queryable map of definitions and cross-file references, then hands agents only the precise context they ask for through what they literally call a unified context API. It even exposes an MCP endpoint.&lt;/p&gt;

&lt;p&gt;Sound familiar?&lt;/p&gt;

&lt;p&gt;It should. That is the entire premise behind the jMRI spec and jCodeMunch.&lt;/p&gt;

&lt;p&gt;GitLab's own Knowledge Graph team wrote down exactly why they built it. In their internal engineering notes they describe treating AGENTS.md as a table of contents instead of an encyclopedia, keeping knowledge in structured docs, and enforcing architecture mechanically. Their stated design goal is agent legibility, on the logic that anything the agent cannot access in-context effectively does not exist.&lt;/p&gt;

&lt;p&gt;A four-person team used that discipline to ship roughly 135,000 lines of Rust in about two weeks, around 95% of it agent-generated. They validated the thesis with their own velocity numbers.&lt;/p&gt;

&lt;p&gt;I have been screaming that from the rooftop since March.&lt;/p&gt;




&lt;h2&gt;
  
  
  Here is where the big-vendor version gets... funny
&lt;/h2&gt;

&lt;p&gt;GitLab's full SDLC graph, the one that actually maps merge requests, pipelines, work items, and code together, is Ultimate tier, GitLab.com only, runs in its own Kubernetes cluster, and is still sitting behind an experiment flag that is off by default. The local code piece writes to a private DuckDB file on your machine and is built to feed GitLab's own stack.&lt;/p&gt;

&lt;p&gt;The insight is correct.&lt;/p&gt;

&lt;p&gt;The delivery vehicle is "buy our most expensive seat, stand up a cluster, and put your source on our infrastructure."&lt;/p&gt;




&lt;h2&gt;
  
  
  The same idea, on your laptop, for the price of a tank of gas
&lt;/h2&gt;

&lt;p&gt;jCodeMunch does the retrieval part locally. It is MCP-native, so any agent that speaks MCP can use it. It works against any repository on any host. Your code never leaves your machine. No recurring enterprise seat. No cluster to babysit.&lt;/p&gt;

&lt;p&gt;This is not theory. Universal Plant Services, an industrial-services company, is already running the full jMunch platform across more than forty engineer seats. Their live dashboard, as of this week:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nearly 48.7 billion tokens saved across the fleet in 72 days, an API-rate value of $177,256.07.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is what jCodeMunch's savings counter put up, in a couple months, at a single company.&lt;/p&gt;

&lt;p&gt;While other organizations are writing postmortems about leaderboards that rewarded waste, a real forty-plus-seat shop is quietly running the efficient version and letting the numbers speak.&lt;/p&gt;




&lt;h2&gt;
  
  
  Honest side-by-side
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;GitLab Orbit&lt;/th&gt;
&lt;th&gt;jCodeMunch&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Where it runs&lt;/td&gt;
&lt;td&gt;Their Kubernetes cluster, GitLab.com only&lt;/td&gt;
&lt;td&gt;Your laptop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Price&lt;/td&gt;
&lt;td&gt;Ultimate-tier seat, ongoing&lt;/td&gt;
&lt;td&gt;One time, per seat or platform&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Repositories&lt;/td&gt;
&lt;td&gt;GitLab-hosted, default branch only&lt;/td&gt;
&lt;td&gt;Any repo, any host&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model lock-in&lt;/td&gt;
&lt;td&gt;Built for GitLab's own stack&lt;/td&gt;
&lt;td&gt;Model-agnostic over MCP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Your source code&lt;/td&gt;
&lt;td&gt;Lives on their infrastructure&lt;/td&gt;
&lt;td&gt;Stays local&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Status&lt;/td&gt;
&lt;td&gt;Experiment, feature-flagged, off by default&lt;/td&gt;
&lt;td&gt;Shipping, running at 40+ seats today&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;GitLab independently reached the same architectural conclusion at the exact moment the rest of the industry is waking up to the bill.&lt;/p&gt;

&lt;p&gt;If your agent cannot retrieve it, it does not exist. GitLab's own team said it. The receipts for ignoring it are showing up in this week's headlines.&lt;/p&gt;

&lt;p&gt;The fix is not "use less AI". It's "use AI less".&lt;/p&gt;

&lt;p&gt;Stop buying the whole book when your robot only needs one page...&lt;/p&gt;

</description>
      <category>aitokencosts</category>
      <category>gitlab</category>
      <category>claudecode</category>
      <category>jcodemunch</category>
    </item>
    <item>
      <title>Saving the World From AI... with AI!</title>
      <dc:creator>J. Gravelle</dc:creator>
      <pubDate>Sat, 16 May 2026 12:46:04 +0000</pubDate>
      <link>https://dev.to/jgravelle/saving-the-world-from-ai-with-ai-4fc2</link>
      <guid>https://dev.to/jgravelle/saving-the-world-from-ai-with-ai-4fc2</guid>
      <description>&lt;h2&gt;
  
  
  I applied SCI for AI to a coding-assistant tool, and the math actually works
&lt;/h2&gt;

&lt;p&gt;The Green Software Foundation ratified SCI for AI five months ago. It's the AI extension to the Software Carbon Intensity standard, the same ISO/IEC 21031 methodology that's been around for software broadly, now with AI-specific boundaries and functional units bolted on.&lt;/p&gt;

&lt;p&gt;If you've never heard of it, that's fine. It's new, the case studies published so far are all from Microsoft, UBS, Google, and Accenture, and the existing literature focuses on training and serving infrastructure rather than the application layer. None of which is where most of us work.&lt;/p&gt;

&lt;p&gt;I wanted to know if the spec held up at the LLM-tooling layer, the part of the stack where MCP servers, retrieval-augmentation tools, context compressors, and developer-facing AI assistants actually live. I had a tool with three months of production telemetry and a number I could point at, so I applied the spec to it.&lt;/p&gt;

&lt;p&gt;The short version: the spec works cleanly there, the math is more interesting than I expected, and there's a piece of intellectual machinery in it that I think is underappreciated and worth showing to other developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;The tool is jCodeMunch, an MCP server I maintain. It sits between AI coding assistants and the codebase they're working on, and serves AST-level summaries and dependency graphs instead of the full-file reads the assistant would otherwise do. The pitch is that the assistant gets the same answers from a tenth of the input tokens.&lt;/p&gt;

&lt;p&gt;Since March 3rd I've been collecting opt-in production telemetry on per-call &lt;code&gt;usage.input_tokens&lt;/code&gt; deltas, what the assistant would have requested versus what the tool actually returned. As of writing, the counter sits at 225,266,057,553 input tokens across 24,645 reporting sessions. The endpoint is public if you want it: &lt;code&gt;https://j.gravelle.us/APIs/savings/total.php&lt;/code&gt;. Returns JSON.&lt;/p&gt;

&lt;p&gt;That's the raw observable. The interesting part is what SCI for AI lets you do with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The spec, briefly
&lt;/h2&gt;

&lt;p&gt;SCI for AI uses the same base formula as classic SCI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SCI = ((E × I) + M) per R
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where &lt;code&gt;E&lt;/code&gt; is energy, &lt;code&gt;I&lt;/code&gt; is grid carbon intensity, &lt;code&gt;M&lt;/code&gt; is amortized embodied emissions, and &lt;code&gt;R&lt;/code&gt; is the functional unit you scale by. What SCI for AI adds is two persona-based boundaries (Consumer, which covers operation and monitoring, i.e. what deployers experience; and Producer, which covers training, fine-tuning, and the upstream lifecycle), plus standardized functional units that let you compare across AI system types.&lt;/p&gt;

&lt;p&gt;The LLM-tooling layer sits squarely at the Consumer boundary. We're not training models. We're affecting what gets sent to inference. The relevant &lt;code&gt;R&lt;/code&gt; for the buyer's experience is per-developer-task: one self-contained unit of work like "explain this function" or "find where authentication is handled." Each task corresponds to one or more LLM calls with measurable token counts.&lt;/p&gt;

&lt;p&gt;That's the whole framework. The rest is putting numbers in the right places.&lt;/p&gt;

&lt;h2&gt;
  
  
  The thing I want to show other developers
&lt;/h2&gt;

&lt;p&gt;When you go to compute per-task energy reduction, you immediately hit a problem: nobody actually knows what per-input-token energy is. The published estimates span an order of magnitude. The peer-reviewed numbers from Microsoft Research's recent &lt;em&gt;Joule&lt;/em&gt; paper (median 0.31 Wh per query, IQR 0.16 to 0.60) are the most defensible, and even they're explicit that their precision is roughly an order of magnitude. ML.ENERGY, TokenPowerBench, and IEA all give different ranges within that uncertainty.&lt;/p&gt;

&lt;p&gt;This is where the spec earns its keep. If a developer-task uses &lt;code&gt;T&lt;/code&gt; input tokens under the baseline and &lt;code&gt;T'&lt;/code&gt; under the with-tool case, and per-token energy is some unknown but bounded &lt;code&gt;e&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;E_baseline = T  × e
E_tool     = T' × e
Reduction  = (T - T') / T
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;e&lt;/code&gt; cancels. The percentage reduction in inference energy equals the percentage reduction in tokens delivered, regardless of which per-token energy estimate you trust. As long as &lt;code&gt;I&lt;/code&gt; and &lt;code&gt;M&lt;/code&gt; are held constant across runs (same grid, same hardware), the per-task SCI for AI score drops by the same proportion.&lt;/p&gt;

&lt;p&gt;This is one of those moments where a spec turns out to be smarter than you'd expect. The ratio is the auditable unit. The absolute conversion is downstream of an unsettled empirical question, and the spec doesn't require you to settle it. You commit to the relationship; the literature handles the magnitude as it improves.&lt;/p&gt;

&lt;p&gt;For jCodeMunch's end-to-end production reduction rate (15 to 25 percent per task, established via a 50-iteration A/B test on a Vue 3 + Firebase codebase, archived in the repo), that means the per-task SCI for AI score drops by 15 to 25 percent, full stop. No methodology fight required.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the absolute numbers look like
&lt;/h2&gt;

&lt;p&gt;If you do want absolutes, here's the conversion against the published energy bounds:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Input-token energy&lt;/th&gt;
&lt;th&gt;225B tokens × energy&lt;/th&gt;
&lt;th&gt;CO₂ at U.S. grid avg (~400 gCO₂/kWh)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0.1 mWh/token (conservative)&lt;/td&gt;
&lt;td&gt;22.5 MWh&lt;/td&gt;
&lt;td&gt;9.0 tonnes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.3 mWh/token (upper)&lt;/td&gt;
&lt;td&gt;67.5 MWh&lt;/td&gt;
&lt;td&gt;27.0 tonnes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For scale: that's between 2 and 6 U.S. household-years of electricity, or 2 to 6 passenger-cars-removed-for-a-year-equivalent on the EPA's standard conversion &lt;em&gt;in our first 10 weeks online&lt;/em&gt;. The grid intensity is U.S. average; the actual number depends on where the LLM provider's inference runs, which they don't disclose at the per-query level. That's a regulatory gap SCI for AI's EU AI Act alignment is meant to close over time.&lt;/p&gt;

&lt;p&gt;The reason I trust the absolutes despite the uncertainty: even the conservative bound is real elimination, not paperwork. SCI for AI explicitly rejects offsets, RECs, PPAs, and the rest of the score-reduction-via-financial-instrument toolkit. The only thing that counts under the standard is causing fewer GPU-seconds to be consumed in the first place. That's the intervention here.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mechanism, if you want it
&lt;/h2&gt;

&lt;p&gt;There are two measurements behind the 15 to 25 percent end-to-end number, and they're worth understanding separately because they measure different things.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Synthetic retrieval-layer benchmark.&lt;/strong&gt; A back-to-back harness compared jCodeMunch's AST-based BM25 retrieval against dense-retrieval RAG at the optimal chunk size, across three open-source repos. Token-per-query reductions ranged 36 to 74 percent against optimized RAG and 99 percent or higher against a full-file-read baseline. These numbers explain why end-to-end savings are achievable. They are not themselves the SCI for AI claim.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;End-to-end A/B test.&lt;/strong&gt; A 50-iteration A/B test on a real Vue 3 + Firebase codebase, contributed by community member @Mharbulous and archived in the repo, ran the same naming-audit task alternating between native Read/Grep/Glob and jCodeMunch's MCP tools. Same model, same iteration count, controlled for session-order effects. The with-tool variant completed more tasks within the timeout (80 percent vs 72 percent), ran shorter on average (299 s vs 318 s), and showed equivalent finding quality. Tool-layer per-task savings landed in the 15 to 25 percent range, lower than the retrieval-layer figure because each iteration also includes variant-independent fixed overhead.&lt;/p&gt;

&lt;p&gt;The end-to-end number is what production telemetry actually accumulates. The retrieval number explains why.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three things I don't know
&lt;/h2&gt;

&lt;p&gt;This is also a real practitioner contribution, which means flagging what I don't have answers to.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Whose &lt;code&gt;I&lt;/code&gt; applies.&lt;/strong&gt; When a developer in one grid region uses an LLM provider whose inference runs in another, the carbon intensity in the SCI for AI calculation should be the inference-side grid, not the developer's. Providers don't disclose this at the per-query level. The math currently uses U.S. average as an upper bound.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How &lt;code&gt;M&lt;/code&gt; is allocated for multi-tenant accelerators.&lt;/strong&gt; The spec allocates embodied emissions by time-share and resource-share. For multi-tenant inference hardware serving millions of inferences per hour across customers, that allocation is non-trivial and relies on disclosure that mostly doesn't exist yet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What baseline aggregate industry comparisons should use.&lt;/strong&gt; A reduction claim is only meaningful relative to a baseline. The most defensible baseline for LLM-tooling claims is the same workflow without the tool, but cross-vendor comparisons would benefit from a published reference workload for the LLM-tooling layer specifically. None exists.&lt;/p&gt;

&lt;p&gt;I've filed these on the &lt;code&gt;Green-Software-Foundation/sci-ai&lt;/code&gt; repo for the working group. If you're working on something adjacent (a context-compression tool, a retrieval optimizer, an MCP server with its own per-task savings story), these are the gaps you'll hit too, and the working group benefits from more practitioners poking at them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fuller version
&lt;/h2&gt;

&lt;p&gt;The detailed case study with the full methodology, the per-repo benchmark tables, the A/B test data, and the failure-mode analysis is in the project wiki: &lt;a href="https://github.com/jgravelle/jcodemunch-mcp/wiki/Token-Reduction-as-an-Energy%E2%80%90Efficiency-Action:-A-225%E2%80%90Billion%E2%80%90Token-Case-Study-Against-SCI-for-AI" rel="noopener noreferrer"&gt;Token Reduction as an Energy-Efficiency Action: A 225-Billion-Token Case Study Against SCI for AI&lt;/a&gt;. Same numbers, more of the math.&lt;/p&gt;

&lt;h2&gt;
  
  
  The point of writing this up
&lt;/h2&gt;

&lt;p&gt;Two reasons, beyond the obvious "I built a thing and the numbers are interesting."&lt;/p&gt;

&lt;p&gt;The first is that SCI for AI is a usable standard for application-layer work, and most developers haven't looked at it. The Consumer-boundary framing fits MCP servers, retrieval tools, and AI-augmented developer tooling more naturally than I expected. If you're working in this part of the stack, the spec gives you a defensible way to talk about per-task carbon impact that doesn't require you to commit to controversial absolute energy numbers. That's worth knowing.&lt;/p&gt;

&lt;p&gt;The second is that the AI-energy conversation has gotten stuck on data-center construction and grid capacity, and the per-task denominator (which the IEA's most recent update explicitly identifies as the leverage point) gets less attention than it should. The software layer is where that denominator moves fastest, and it's where the lowest-capital interventions live. Worth more developer mindshare than it currently gets.&lt;/p&gt;

&lt;p&gt;If you build something in this space, publish your numbers. Even rough numbers. The literature improves through case studies, and right now the case-study record is dominated by the largest organizations in the world. More practitioner data is good for everyone...&lt;/p&gt;

&lt;p&gt;-jjg&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>devops</category>
      <category>development</category>
    </item>
    <item>
      <title>Headless Claude, Done Right: Slice-Level Retrieval and the Subscription Trap</title>
      <dc:creator>J. Gravelle</dc:creator>
      <pubDate>Wed, 06 May 2026 14:07:47 +0000</pubDate>
      <link>https://dev.to/jgravelle/headless-claude-done-right-slice-level-retrieval-and-the-subscription-trap-50ip</link>
      <guid>https://dev.to/jgravelle/headless-claude-done-right-slice-level-retrieval-and-the-subscription-trap-50ip</guid>
      <description>&lt;h3&gt;
  
  
  An open-source CLI that respects your Claude Pro auth, retrieves only what it needs, and stays inside the lines Anthropic drew in their TOS.
&lt;/h3&gt;

&lt;p&gt;= = =&lt;/p&gt;

&lt;p&gt;Spawn &lt;code&gt;claude -p&lt;/code&gt; from a Python subprocess without the right precautions and you'll silently bill your Anthropic API account instead of using the Claude Pro subscription you already pay for. For a 799,000-token query, that's the difference between $0.00 and $11.99. Two environment variable strips later, my CLI does the right thing by default. And that's the smallest piece of what makes this work.&lt;/p&gt;

&lt;p&gt;This is a write-up of &lt;a href="https://github.com/jgravelle/jragmunch-cli" rel="noopener noreferrer"&gt;jragmunch-cli&lt;/a&gt;, an open-source tool I built (Apache 2.0, on PyPI) that wraps the official &lt;code&gt;claude -p&lt;/code&gt; binary with a few opinions: respect the user's auth, retrieve only what's needed, and stay inside the lines Anthropic actually drew in their own legal docs. The interesting parts are the ones that aren't obvious from the README.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why your subscription quietly turns into an API bill
&lt;/h2&gt;

&lt;p&gt;Anthropic's &lt;code&gt;claude&lt;/code&gt; CLI binary (the one you install with &lt;code&gt;npm install -g @anthropic-ai/claude-code&lt;/code&gt;) is auth-flexible by design. It will use whatever credentials it finds, in priority order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;ANTHROPIC_API_KEY&lt;/code&gt; if set&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ANTHROPIC_AUTH_TOKEN&lt;/code&gt; if set&lt;/li&gt;
&lt;li&gt;Your Claude Pro / Max OAuth login otherwise&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's reasonable behavior for the binary as a primitive. The footgun is what happens when you spawn it as a subprocess from Python.&lt;/p&gt;

&lt;p&gt;By default, &lt;code&gt;subprocess.Popen&lt;/code&gt; (and friends) pass the parent process's full environment to the child. If you have &lt;code&gt;ANTHROPIC_API_KEY&lt;/code&gt; exported in your shell (because, say, you also use the API from other scripts), every &lt;code&gt;claude -p&lt;/code&gt; invocation your tool makes will silently pick that up and bill your API account. You won't see an error. You won't see a warning. You'll just see a bill at the end of the month and a perfectly preserved subscription quota you never touched.&lt;/p&gt;

&lt;p&gt;The fix is mechanically tiny:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;

&lt;span class="n"&gt;env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ANTHROPIC_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ANTHROPIC_AUTH_TOKEN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-p&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--output-format&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stream-json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&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;Three lines. But the discipline behind it matters: any tool that spawns &lt;code&gt;claude -p&lt;/code&gt; from a parent process should default to subscription mode and require an opt-in flag to switch to API. jRAGmunch-CLI's &lt;code&gt;--use-api&lt;/code&gt; flag is exactly that, and &lt;code&gt;jragmunch doctor&lt;/code&gt; will tell you which mode you're in before you run anything expensive.&lt;/p&gt;

&lt;p&gt;If you're wrapping &lt;code&gt;claude -p&lt;/code&gt; in your own scripts, copy the pattern. It'll save someone a surprise bill.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bigger problem: dumping your repo at the model
&lt;/h2&gt;

&lt;p&gt;Even with auth handled correctly, the default pattern for "ask Claude about my repo" still wastes obscene amounts of tokens. The naive pattern looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Walk the repo&lt;/li&gt;
&lt;li&gt;Concatenate every relevant file into one giant string&lt;/li&gt;
&lt;li&gt;Stuff it into the prompt&lt;/li&gt;
&lt;li&gt;Hope the model finds what it needs&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is what most "chat with your repo" wrappers do, and it's what burns through Claude Pro session limits in fifteen minutes flat. The 2.5GB Node.js source tree I demo with would need around 21 million tokens to fit in one prompt. Even if that fit (it doesn't), you'd be paying for the model to read 100% of the code to answer a question that touches 0.1% of it.&lt;/p&gt;

&lt;p&gt;Here's a real run from &lt;code&gt;AskClaude.py&lt;/code&gt;, the side-by-side demo script in the repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;In its raw form, your request may have used as many as 799,037 tokens,
at a cost of $11.99.

Using jRAGmunch-CLI, our call to Opus 4.7 only used 24,771 tokens.

By using your subscription WITHIN THE TERMS OF ANTHROPIC'S TOS, you paid
$0.00 and used a nearly imperceptible fractional percentage of your quota.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;799K tokens versus 24K. Same question, same answer quality. The difference isn't the model. The difference is what gets sent to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Slice, don't dump
&lt;/h2&gt;

&lt;p&gt;The retrieval layer is where the real engineering happens. jRAGmunch-CLI delegates retrieval to &lt;a href="https://github.com/jgravelle/jcodemunch-mcp" rel="noopener noreferrer"&gt;jcodemunch-mcp&lt;/a&gt;, a separate MCP server I maintain that does AST-level symbol extraction across 70+ languages via tree-sitter.&lt;/p&gt;

&lt;p&gt;Here's the conceptual difference between this and traditional RAG.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Traditional RAG.&lt;/strong&gt; Chop the codebase into arbitrary text chunks. Embed each chunk. When a query comes in, embed the query, find the chunks with the highest cosine similarity, send those to the model. The retrieval is statistical and approximate. It can miss things. It can include things that look related but aren't. It treats your code as if it were prose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Slice-level retrieval.&lt;/strong&gt; Parse the codebase into an AST. When a query references a symbol (function name, class, identifier), look up that exact symbol in the index. Return the actual function body. Trace the actual import graph. The retrieval is structural and exact. If you ask for &lt;code&gt;AuthMiddleware.verify&lt;/code&gt;, you get &lt;code&gt;AuthMiddleware.verify&lt;/code&gt;, not the seven chunks that happened to contain the word "auth."&lt;/p&gt;

&lt;p&gt;Surgical, not statistical.&lt;/p&gt;

&lt;p&gt;The result is what shows up in jRAGmunch-CLI's &lt;code&gt;_meta&lt;/code&gt; output on every call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;[tokens in=24 out=1273  cost actual=$&lt;/span&gt;0.0000 &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;notional&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;.5334, &lt;span class="nv"&gt;auth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;subscription&lt;span class="o"&gt;)&lt;/span&gt;  &lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;27549ms]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;actual&lt;/code&gt; is what you really paid (zero, in subscription mode). &lt;code&gt;notional&lt;/code&gt; is what the same work would have cost via the API at Opus 4.7's input rate. &lt;code&gt;auth&lt;/code&gt; is which credential path the subprocess used. Every verb returns this. You always know what you actually spent and what you would have spent.&lt;/p&gt;

&lt;p&gt;That transparency matters more than it sounds. Most LLM tooling hides cost behind the abstraction. jRAGmunch-CLI makes you look at it on every call. After a week of that, your intuition for "what's a reasonable token budget for this question" sharpens dramatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  It's not just &lt;code&gt;ask&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The verb most people see first is &lt;code&gt;jragmunch ask&lt;/code&gt;, because that's the obvious "chat with your repo" use case. But the more interesting verbs are downstream of that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;jragmunch index&lt;/code&gt; indexes a repo via jcodemunch (one-time, then incremental on subsequent calls).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;jragmunch review&lt;/code&gt; does diff-aware PR review against a git range.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;jragmunch changelog&lt;/code&gt; summarizes changes since a tag.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;jragmunch refactor&lt;/code&gt; fans out batch refactors across matched symbols.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;jragmunch tests&lt;/code&gt; generates tests for symbols that don't have them.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;jragmunch sweep&lt;/code&gt; does pattern-driven cleanup across the repo.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;jragmunch run&lt;/code&gt; is a power-user passthrough for direct prompts.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;jragmunch doctor&lt;/code&gt; verifies your CLI + MCP wiring before you spend tokens.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;review&lt;/code&gt; and &lt;code&gt;refactor&lt;/code&gt; verbs are where this stops looking like a Q&amp;amp;A wrapper and starts looking like an agentic CLI toolkit. &lt;code&gt;review&lt;/code&gt; reads your diff, retrieves the surrounding symbol context that the diff actually touches (not the whole file, not the whole repo, just the symbols affected), and runs a structured review pass. &lt;code&gt;refactor&lt;/code&gt; does fan-out work across multiple call sites in parallel, with each subprocess getting only the slice it needs.&lt;/p&gt;

&lt;p&gt;That fan-out pattern is also where the TOS line gets interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  When subscription mode is the right answer (and when it isn't)
&lt;/h2&gt;

&lt;p&gt;Anthropic's &lt;a href="https://code.claude.com/docs/en/legal-and-compliance" rel="noopener noreferrer"&gt;Claude Code Legal and Compliance docs&lt;/a&gt; draw a bright line that most wrappers ignore. Paraphrased:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Individual ordinary use&lt;/em&gt; of Claude Code on your own machine, with your own subscription, is permitted.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Business, always-on, multi-contributor, or high-throughput&lt;/em&gt; use should run against the API with an API key.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;jRAGmunch-CLI's defaults are tuned to that line. Subscription mode by default for solo interactive work; explicit &lt;code&gt;--use-api&lt;/code&gt; for anything that crosses into the second bucket. The README ships a decision table covering the typical cases:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;You are…&lt;/th&gt;
&lt;th&gt;Recommended mode&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A solo developer running verbs interactively on your own machine&lt;/td&gt;
&lt;td&gt;subscription (default)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A solo developer running &lt;code&gt;jragmunch review&lt;/code&gt; in your own personal repo's CI&lt;/td&gt;
&lt;td&gt;subscription (default), with &lt;code&gt;CLAUDE_CODE_OAUTH_TOKEN&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A team running CI bots on a shared / commercial repo&lt;/td&gt;
&lt;td&gt;&lt;code&gt;--use-api&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-developer or commercial automation&lt;/td&gt;
&lt;td&gt;&lt;code&gt;--use-api&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Heavy parallel fan-out (&lt;code&gt;refactor --parallel 16&lt;/code&gt;, etc.)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;--use-api&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This isn't a workaround. It isn't a loophole. Anthropic explicitly permits the first column and explicitly directs the second column to the API. jRAGmunch-CLI just makes the right default for each case the easy default.&lt;/p&gt;

&lt;p&gt;The recent wave of "I got rate-limited on Claude Pro after two days" complaints comes mostly from tools that don't respect this line. They run on a personal subscription, fan out twenty parallel subprocesses doing CI-grade work, then act surprised when the throttle drops. If you respect the line Anthropic drew, your subscription stays healthy. If you don't, it doesn't. jRAGmunch-CLI is opinionated about which side of the line you're on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;If you have the &lt;code&gt;claude&lt;/code&gt; CLI on your PATH and &lt;code&gt;jCodemunch-MCP&lt;/code&gt; registered as an MCP server, getting started is two commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;jragmunch
jragmunch doctor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;doctor&lt;/code&gt; will tell you whether your auth resolves to subscription or API, whether the MCP server is reachable, and whether anything is misconfigured before you spend tokens. From there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jragmunch index &lt;span class="nt"&gt;--repo&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
jragmunch ask &lt;span class="s2"&gt;"how does auth work in this repo"&lt;/span&gt;
jragmunch review &lt;span class="nt"&gt;--since&lt;/span&gt; main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want the side-by-side cost comparison I quoted earlier, clone the repo and run &lt;code&gt;python AskClaude.py&lt;/code&gt;. It prompts for a repo path and a question, then prints the answer plus the token math. Use it as a sanity check on your own codebases or as a template for embedding jRAGmunch-CLI into other tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  One last thing
&lt;/h2&gt;

&lt;p&gt;The repo is brand new. Star it if it's useful. File issues if it isn't. Send a PR if you've got opinions about which verb should ship next.&lt;/p&gt;

&lt;p&gt;The 2.5GB Node.js demo, the live cost math, and a fuller walkthrough are in the AI Tips With J video premiering today. Both links below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://github.com/jgravelle/jragmunch-cli" rel="noopener noreferrer"&gt;github.com/jgravelle/jragmunch-cli&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Video:&lt;/strong&gt; &lt;a href="https://www.youtube.com/watch?v=ZP0OPSq0jcQ" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=ZP0OPSq0jcQ&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Comparison page (vs. RAG, vs. raw file reads):&lt;/strong&gt; &lt;a href="https://j.gravelle.us/jCodeMunch/versus.php" rel="noopener noreferrer"&gt;j.gravelle.us/jCodeMunch/versus.php&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Slice, don't dump.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;jjg&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>clau</category>
      <category>mcp</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How we measured 99.6% token reduction across 15 task-runs</title>
      <dc:creator>J. Gravelle</dc:creator>
      <pubDate>Thu, 30 Apr 2026 11:31:33 +0000</pubDate>
      <link>https://dev.to/jgravelle/how-we-measured-996-token-reduction-across-15-task-runs-hn2</link>
      <guid>https://dev.to/jgravelle/how-we-measured-996-token-reduction-across-15-task-runs-hn2</guid>
      <description>&lt;h1&gt;
  
  
  Two months after publishing the headline, here are the receipts.
&lt;/h1&gt;

&lt;p&gt;Two months ago I published &lt;em&gt;"Your AI Agent Is Dumpster Diving Through Your Code."&lt;/em&gt; The most common reply was some flavor of: &lt;em&gt;"Cool numbers, but how did you actually measure them?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Fair question. Here's the answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we measured
&lt;/h2&gt;

&lt;p&gt;The jCodeMunch benchmark measures &lt;strong&gt;retrieval token efficiency&lt;/strong&gt; — how many LLM input tokens a code-exploration tool consumes compared to reading all source files. It does not measure answer quality, latency, or end-to-end task completion. Those are separate axes (we measure precision separately in jMunchWorkbench, but that's a different post).&lt;/p&gt;

&lt;p&gt;Three repos, five queries, run on 2026-03-28:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Repository&lt;/th&gt;
&lt;th&gt;Files&lt;/th&gt;
&lt;th&gt;Symbols&lt;/th&gt;
&lt;th&gt;Baseline tokens&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;expressjs/express&lt;/td&gt;
&lt;td&gt;165&lt;/td&gt;
&lt;td&gt;181&lt;/td&gt;
&lt;td&gt;137,978&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fastapi/fastapi&lt;/td&gt;
&lt;td&gt;951&lt;/td&gt;
&lt;td&gt;5,325&lt;/td&gt;
&lt;td&gt;699,425&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gin-gonic/gin&lt;/td&gt;
&lt;td&gt;98&lt;/td&gt;
&lt;td&gt;1,489&lt;/td&gt;
&lt;td&gt;187,018&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The five queries cover the most common code-exploration intents I see in the wild: &lt;code&gt;router route handler&lt;/code&gt;, &lt;code&gt;middleware&lt;/code&gt;, &lt;code&gt;error exception&lt;/code&gt;, &lt;code&gt;request response&lt;/code&gt;, &lt;code&gt;context bind&lt;/code&gt;. Three repos × five queries = &lt;strong&gt;15 task-runs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Total baseline cost across all 15: &lt;strong&gt;5,122,105 tokens.&lt;/strong&gt;&lt;br&gt;
Total jcodemunch cost across all 15: &lt;strong&gt;19,406 tokens.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Reduction: &lt;strong&gt;99.6% average.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How the runs work
&lt;/h2&gt;

&lt;p&gt;For each query, the harness does two things and compares.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Baseline:&lt;/strong&gt; concatenate every file in the repo, tokenize, count. This is the "read everything first" agent — the minimum cost to put the entire codebase in context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;jcodemunch:&lt;/strong&gt; call &lt;code&gt;search_symbols(query, max_results=5)&lt;/code&gt;, then &lt;code&gt;get_symbol_source()&lt;/code&gt; on the top 3 matching symbol IDs. Total tokens = search response tokens + 3 × symbol source tokens.&lt;/p&gt;

&lt;p&gt;AI summaries are &lt;strong&gt;disabled&lt;/strong&gt; during benchmarking (signature-only fallback). Without that, jcodemunch numbers would look even better, but it would conflate retrieval efficiency with summarization efficiency, and those are separable concerns.&lt;/p&gt;

&lt;p&gt;Token counts come from the &lt;strong&gt;serialized JSON response strings&lt;/strong&gt;, not raw source bytes — JSON field names and structure overhead are included. Slightly understates savings, but the count is deterministic and reproducible.&lt;/p&gt;

&lt;p&gt;Tokenizer: &lt;code&gt;tiktoken&lt;/code&gt; with &lt;code&gt;cl100k_base&lt;/code&gt; encoding. Used by GPT-4 and compatible with Claude estimates within ~5%.&lt;/p&gt;

&lt;h2&gt;
  
  
  The "common misreadings"
&lt;/h2&gt;

&lt;p&gt;The methodology doc has a section called Common Misreadings. It addresses the four pushbacks I get every time I publish a number.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"The claim is up to 99%."&lt;/strong&gt; No — the primary claim is &lt;strong&gt;99.6% average&lt;/strong&gt; across all 15 task-runs. Individual queries reach 99.9% on large repos with tight symbol matches (&lt;code&gt;error exception&lt;/code&gt; on fastapi/fastapi: 99.9%, 801× reduction). The 99.6% aggregate is the honest headline across the current index state.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"I tested it on a different repo and got 80%."&lt;/strong&gt; Results vary by repo structure. Flat script collections — repositories of hundreds of unrelated standalone scripts — produce lower savings, because the symbol index can't distinguish which script is relevant to a given query, and the agent still has to scan broadly. The benchmark repos (Express, FastAPI, Gin) are structured application codebases where symbol-based navigation is most effective. Testing a flat script collection and comparing to our benchmark is apples-to-oranges. I say so out loud because pretending otherwise would be dishonest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"The benchmark is cherry-picked."&lt;/strong&gt; The three repos were chosen to represent common backend frameworks across different languages — JavaScript, Python, Go. No file filtering beyond standard skip patterns. The harness (&lt;code&gt;benchmarks/harness/run_benchmark.py&lt;/code&gt;) and query corpus (&lt;code&gt;benchmarks/tasks.json&lt;/code&gt;) are in the repo. Run them yourself. Publish your numbers. If they're better than mine, I'll cite you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"The baseline is unrealistic."&lt;/strong&gt; It is — but it's intentionally a &lt;em&gt;lower bound&lt;/em&gt;. Real agents re-read files, branch across sessions, and load documentation. Actual production baseline costs are higher than what I report. That makes the 99.6% number a conservative floor, not a ceiling.&lt;/p&gt;

&lt;h2&gt;
  
  
  What others have measured independently
&lt;/h2&gt;

&lt;p&gt;Two reviewers ran their own numbers and published them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Artur Skowroński (VirtusLab GitHub All-Stars #15):&lt;/strong&gt; &lt;em&gt;"roughly 80% fewer tokens, or 5× more efficient — index once, query cheaply forever."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Julian Horsey (Geeky Gadgets):&lt;/strong&gt; &lt;em&gt;"3,850 tokens reduced to just 700 — a 5.5× improvement."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;These don't contradict the 99.6%. They're testing different workloads at different scales. Smaller per-query savings × hundreds of queries per session = the same compounding effect at the larger scale. Multiple methodologies converging in the same direction is exactly what you want from a benchmark you'd actually rely on.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to run it yourself
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;jcodemunch-mcp tiktoken

jcodemunch index_repo expressjs/express
jcodemunch index_repo fastapi/fastapi
jcodemunch index_repo gin-gonic/gin

python benchmarks/harness/run_benchmark.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every release in v1.76.0+ runs the benchmark in CI with a regression gate at 0.02 — if any aggregate metric drops by more than 2% versus the saved baseline, the build fails. I don't ship without the receipts.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means for you
&lt;/h2&gt;

&lt;p&gt;If you're building agents on Claude Max, hitting context-window pain, or paying API bills that scale with token count: don't take my word for it. Run the calculator on your own stack.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://j.gravelle.us/jCodeMunch/token-tax-calculator.php" rel="noopener noreferrer"&gt;Token Tax Calculator&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It tells you what you're spending today, what jcodemunch saves, and what that maps to annually. Takes 60 seconds. Costs nothing.&lt;/p&gt;

&lt;p&gt;The benchmark is a number. Your own stack is the number that matters.&lt;/p&gt;

&lt;p&gt;—-jjg&lt;br&gt;
&lt;a href="https://github.com/jgravelle/mcp-retrieval-spec" rel="noopener noreferrer"&gt;github.com/jgravelle/mcp-retrieval-spec&lt;/a&gt;&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>claude</category>
      <category>ai</category>
      <category>python</category>
    </item>
    <item>
      <title>I didn't set out to build a sustainability tool...</title>
      <dc:creator>J. Gravelle</dc:creator>
      <pubDate>Tue, 21 Apr 2026 15:43:12 +0000</pubDate>
      <link>https://dev.to/jgravelle/i-didnt-set-out-to-build-a-sustainability-tool-cbh</link>
      <guid>https://dev.to/jgravelle/i-didnt-set-out-to-build-a-sustainability-tool-cbh</guid>
      <description>&lt;p&gt;...but only seven weeks in, we've accidentally saved enough electricity to power roughly 65 American households for a year, and enough avoided CO₂ to take 64 gasoline cars off the road.&lt;/p&gt;

&lt;p&gt;I set out to fix a dumb problem: LLM coding agents load entire files into their context window to answer questions about single functions. That's expensive in dollars, it's slow, and it pollutes the context with junk the model doesn't need. So I wrote jCodeMunch, an MCP server that returns &lt;em&gt;only&lt;/em&gt; the symbol, slice, or bundle the agent actually asked about.&lt;/p&gt;

&lt;p&gt;Since I shipped the telemetry on March 3, 2026, opted-in installs have collectively avoided &lt;strong&gt;172,000,000,000 tokens&lt;/strong&gt; of LLM inference.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;estimate_savings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw_bytes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response_bytes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;max&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw_bytes&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;response_bytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="mi"&gt;4&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 the whole thing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;raw_bytes&lt;/code&gt; = the bytes the agent &lt;em&gt;would&lt;/em&gt; have loaded under "cat the file into context". Whole-file reads are the default retrieval primitive for every major coding agent today.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;response_bytes&lt;/code&gt; = the bytes jCodeMunch actually returned.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;// 4&lt;/code&gt; = OpenAI's published bytes-per-token approximation. Within 5% of tiktoken on real code.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;max(0, ...)&lt;/code&gt; = if my response is somehow bigger than the baseline, I count zero. No anti-savings allowed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every single API call emits a &lt;code&gt;_meta&lt;/code&gt; block with the delta. You can audit any call. The accumulator flushes to disk every three calls and ships anonymous deltas (opt-out with one flag) to a public endpoint. 172B is the sum.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the number is a floor, not a ceiling
&lt;/h2&gt;

&lt;p&gt;I made four choices that all bias the number down:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;File-level dedup.&lt;/strong&gt; A call that touches 5 symbols in one file counts the file once, not five times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;max(0, ...)&lt;/code&gt; clamp.&lt;/strong&gt; Never negative.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Opt-in telemetry only.&lt;/strong&gt; Users who never enabled reporting don't count.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single-file baseline.&lt;/strong&gt; I compare against "read one whole file." A real agent doing grep-and-cat across a repo would've loaded way more.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Telemetry participation is opt-in. The &lt;em&gt;real&lt;/em&gt; savings are higher than 172B. I just can't prove numbers I didn't measure. A valid criticism of this number might be: "Dude. It's way higher than THAT."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jgravelle/jmunch-mcp" rel="noopener noreferrer"&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%2Farticles%2Fa9neabyn4a5dk8zh62bz.png" alt=" " width="436" height="261"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tokens → kilowatt-hours
&lt;/h2&gt;

&lt;p&gt;Here's where it stops being cute and starts mattering.&lt;/p&gt;

&lt;p&gt;Peer-reviewed estimates of LLM inference energy cluster around &lt;strong&gt;0.004 Wh per token&lt;/strong&gt; on a modern H100 stack (Epoch AI, Altman's own disclosure, Google's median text query, and the Surfshark meta-analysis all triangulate here).&lt;/p&gt;

&lt;p&gt;172B tokens × 0.004 Wh/token = &lt;strong&gt;688,000 kWh avoided&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That's:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The annual electricity use of &lt;strong&gt;~65 average US homes&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;~292 metric tons&lt;/strong&gt; of CO₂ not emitted (US grid avg)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;~64 gasoline cars&lt;/strong&gt; off the road for a year&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;~14,600 gallons&lt;/strong&gt; of gasoline not burned&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From one MCP server. That's free to the general public, and costs $79 for commercial users. Once.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part nobody in the sustainability conversation is talking about
&lt;/h2&gt;

&lt;p&gt;AWS has publicly stated inference accounts for &lt;strong&gt;more than 90%&lt;/strong&gt; of an LLM's lifecycle energy. Training is a one-time capital expense. Inference is a forever bill. And the inference bill is bloated with tokens that shouldn't exist — context stuffed with entire files when the model needed one function, whole repos ingested when a symbol lookup would do.&lt;/p&gt;

&lt;p&gt;Every AI-sustainability paper I've read treats this as an unsolvable infrastructure problem: build bigger data centers, run them on renewables, hope for the best. Nobody asks the obvious question: &lt;strong&gt;what if we just sent the model less garbage?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The answer turns out to be worth 64 cars' worth of CO₂, per small indie product, in eight weeks.&lt;/p&gt;

&lt;p&gt;Could this sort of frugality allow AI to continue to thrive exponentially with only 1/8th of the proposed new power plants? 1/10th?&lt;/p&gt;

&lt;p&gt;I'm not a climate researcher. I'm a developer in Wisconsin who got tired of watching my token bill. But I think there's a bigger story here, and I don't think it's mine alone to tell. Context-size discipline might be the single highest-leverage thing the AI tooling community can do for energy. Every retrieval-augmented anything is, in aggregate, a carbon-reduction tool. Most of us just don't measure it.&lt;/p&gt;

&lt;p&gt;jCodeMunch does. The counter is live at [jcodemunch.com]. The formula is on GitHub. If you want to challenge the math, please do — the methodology doc lists every source citation, every conversion constant, and every assumption.&lt;/p&gt;

&lt;p&gt;Until somebody does, the number stands: &lt;strong&gt;172 billion tokens, 688,000 kWh, 64 cars. And counting...&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>llm</category>
      <category>mcp</category>
      <category>performance</category>
      <category>tooling</category>
    </item>
  </channel>
</rss>
