<?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: Murat Sert</title>
    <description>The latest articles on DEV Community by Murat Sert (@msertdev).</description>
    <link>https://dev.to/msertdev</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%2F4241670%2F620645f8-3cbb-4529-a2ff-7aea940463a4.jpg</url>
      <title>DEV Community: Murat Sert</title>
      <link>https://dev.to/msertdev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/msertdev"/>
    <language>en</language>
    <item>
      <title>I measured what my Claude Code setup costs on every request. Most of my skills had gone blank.</title>
      <dc:creator>Murat Sert</dc:creator>
      <pubDate>Thu, 12 Nov 2026 19:07:15 +0000</pubDate>
      <link>https://dev.to/msertdev/i-measured-what-my-claude-code-setup-costs-on-every-request-most-of-my-skills-had-gone-blank-2eg3</link>
      <guid>https://dev.to/msertdev/i-measured-what-my-claude-code-setup-costs-on-every-request-most-of-my-skills-had-gone-blank-2eg3</guid>
      <description>&lt;p&gt;Claude Code sent 74,500 tokens with my first message of the day, before it had read a single word I typed. About 22,000 of those came from plugins, skills, MCP servers and hooks I had installed over a few months, most of which I had forgotten about.&lt;/p&gt;

&lt;p&gt;That overhead is resent on every turn of every session. It drains your usage limit, fills the context window sooner (so sessions compact earlier), and, as it turns out, quietly makes Claude worse at picking the right skill.&lt;/p&gt;

&lt;p&gt;Here's how I measured it, the one finding that surprised me, and the small open-source tool I built so you can check your own setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the numbers come from
&lt;/h2&gt;

&lt;p&gt;Claude Code writes a transcript of every session to &lt;code&gt;~/.claude/projects/&amp;lt;project&amp;gt;/&amp;lt;session&amp;gt;.jsonl&lt;/code&gt;. Besides the conversation, it records what was loaded at startup as separate entries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;skill_listing&lt;/code&gt;: every skill name and description the model is shown&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;deferred_tools_delta&lt;/code&gt;: the names of all deferred tools, including every MCP tool, plus MCP servers that &lt;strong&gt;failed to connect&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mcp_instructions_delta&lt;/code&gt;: instruction blocks MCP servers inject&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;agent_listing_delta&lt;/code&gt;: the subagent types on offer&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;hook_success&lt;/code&gt;: output of your &lt;code&gt;SessionStart&lt;/code&gt; hooks, which often lands in context&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And for each API call, the assistant entry carries the real usage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"usage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;"input_tokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"cache_creation_input_tokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;40260&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"cache_read_input_tokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;34273&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add those three and you get the exact size of the first request: no estimate, that's what the API billed. Every other number in this post is broken down from there.&lt;/p&gt;

&lt;h2&gt;
  
  
  The finding: past ~30,000 characters, your skills go blank
&lt;/h2&gt;

&lt;p&gt;When I opened the &lt;code&gt;skill_listing&lt;/code&gt; entry, most lines looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- some-plugin:some-skill
- another-skill
- yet-another:skill
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No description. Just names.&lt;/p&gt;

&lt;p&gt;The listing text was almost exactly 30,000 characters in every session I checked, no matter how many skills I had installed. Once your skills don't fit, Claude Code starts dropping descriptions and keeps only the names. In my setup, &lt;strong&gt;220 of 283 skills&lt;/strong&gt; were listed by name only. In an older session with 672 skills installed, 642 had no description.&lt;/p&gt;

&lt;p&gt;Why that matters: the description is how the model decides when to use a skill. A bare name like &lt;code&gt;review&lt;/code&gt; or &lt;code&gt;start&lt;/code&gt; tells it almost nothing. So every skill you installed "just in case" isn't only costing tokens. Claude Code seems to keep descriptions for the skills you've used recently (all 12 of mine kept theirs), but everything else goes blank, including a skill you just installed or only reach for once a month. The model can't tell when to use those.&lt;/p&gt;

&lt;p&gt;I haven't seen this documented anywhere, and the exact limit may change between versions, so treat ~30k as what I observed, not a spec.&lt;/p&gt;

&lt;h2&gt;
  
  
  What else was in there
&lt;/h2&gt;

&lt;p&gt;Once everything was attributed to where it came from, a few other things showed up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MCP servers that failed to connect&lt;/strong&gt; at startup, every session, for weeks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;36 MCP servers I had never signed in to&lt;/strong&gt;, each still listing its &lt;code&gt;authenticate&lt;/code&gt; and &lt;code&gt;complete_authentication&lt;/code&gt; tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Duplicate skills&lt;/strong&gt;: the same skill name shipped by two different plugins.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One skill whose description alone cost about 3,000 tokens&lt;/strong&gt; per request. I had used it once.&lt;/li&gt;
&lt;li&gt;And the obvious one: 272 of 283 skills hadn't been used in 30 days.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  deadweight
&lt;/h2&gt;

&lt;p&gt;I turned all of this into a CLI called &lt;strong&gt;deadweight&lt;/strong&gt;. It reads the same transcripts and prints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ deadweight

  Before you type a word, every request carries 61.2k tokens
  measured from your latest session; median of recent sessions 63.8k
  ~19.4k from your setup · ~41.8k from Claude Code itself (system prompt + 18 tools)

  WHAT YOUR SETUP ADDS
  Deferred tool names (412)            ~7.1k  ████████████████████████
  Skill listings (214)                 ~6.2k  █████████████████████
  Hook injections (3)                  ~3.4k  ███████████▌
  MCP server instructions (4)          ~2.1k  ███████▏
  Agent listings (12)                   ~600  ██

  BIGGEST SOURCES
  name                           type           tokens    used  contents
  github                         mcp server      ~3.9k    212×  91 tools
  kitchen-sink                   plugin          ~3.6k   never  64 tools · 22 skills
  workflow-kit                   plugin          ~2.6k     14×  hooks 2.2k · 11 skills
  playwright                     mcp server      ~1.4k   never  33 tools

  PROBLEMS
  ✗ 151 of 214 skills are listed without a description: the skill listing is full
  ✗ 2 MCP servers failed to connect at startup
  ! 9 MCP servers never signed in, still listing 18 auth-only tools
  ! 198 of 214 listed skills were not used in 30 days (~5.1k per request)

  Run deadweight fix to disable 6 unused plugins and park 11 unused skills and save ~6.8k tokens per request.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(That's an illustrative example; your output will be your own setup.)&lt;/p&gt;

&lt;p&gt;How it works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Measure&lt;/strong&gt;: the total is the billed size of the first request in your latest session.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Attribute&lt;/strong&gt;: every skill line, tool name, instruction block, agent and hook injection is traced to the plugin, skill, MCP server or connector that added it. Hook commands are matched against each plugin's &lt;code&gt;hooks.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check usage&lt;/strong&gt;: every transcript from the last 30 days, subagents included, is scanned for &lt;code&gt;Skill&lt;/code&gt; calls, MCP tool calls, agent launches and slash commands.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then &lt;code&gt;deadweight fix&lt;/code&gt; disables unused plugins and moves unused skills aside, and &lt;code&gt;deadweight undo&lt;/code&gt; puts everything back.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making "fix" safe
&lt;/h2&gt;

&lt;p&gt;A tool that edits your config needs to be boring and predictable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Read-only by default.&lt;/strong&gt; Only &lt;code&gt;fix&lt;/code&gt; and &lt;code&gt;undo&lt;/code&gt; write, and both ask first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nothing is deleted.&lt;/strong&gt; Plugins are set to &lt;code&gt;enabledPlugins: false&lt;/code&gt; in &lt;code&gt;settings.json&lt;/code&gt;, not uninstalled. Skills are moved into a backup folder.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Everything is backed up.&lt;/strong&gt; Each run writes a manifest and a copy of &lt;code&gt;settings.json&lt;/code&gt; to &lt;code&gt;~/.claude/deadweight/backups/&amp;lt;timestamp&amp;gt;/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plugins with hooks are skipped.&lt;/strong&gt; A memory or safety plugin can do useful work without ever showing up as "used", so those need &lt;code&gt;--include-hooked&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It refuses with too little history.&lt;/strong&gt; With fewer than 5 sessions, "unused" doesn't mean much.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No secrets, no network.&lt;/strong&gt; From &lt;code&gt;.claude.json&lt;/code&gt; it only reads MCP server &lt;em&gt;names&lt;/em&gt;, never commands, env vars or headers. A test asserts that secret values never reach the output.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Built in Rust, with Claude Code
&lt;/h2&gt;

&lt;p&gt;deadweight is a single Rust binary. Transcripts get big (mine were 1.4 GB), so files are scanned in parallel with &lt;code&gt;rayon&lt;/code&gt;, and lines are pre-filtered with a cheap substring check before any JSON parsing. A full scan of 41 sessions and 400+ subagent runs takes about a second.&lt;/p&gt;

&lt;p&gt;I built it with Claude Code as my pair programmer: surveying existing tools so I didn't build yet another usage tracker, reverse-engineering the transcript format on my machine, writing the Rust and an end-to-end test suite that runs against a fake &lt;code&gt;~/.claude&lt;/code&gt; directory. The tests caught a real bug early: skill names like &lt;code&gt;plugin:skill&lt;/code&gt; were being split on the wrong colon, which silently gave one skill's size to its neighbour.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caveats
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;total is measured&lt;/strong&gt;. The per-item breakdown is &lt;strong&gt;estimated&lt;/strong&gt; from text length, since there's no local tokenizer.&lt;/li&gt;
&lt;li&gt;Claude Code deletes transcripts after &lt;code&gt;cleanupPeriodDays&lt;/code&gt; (30 by default), so "unused" can only look that far back. Use &lt;code&gt;--keep&lt;/code&gt; for things you use rarely.&lt;/li&gt;
&lt;li&gt;The ~30k-character listing limit is what I observed, not documented behaviour.&lt;/li&gt;
&lt;/ul&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo install deadweight
deadweight
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prebuilt binaries for macOS, Linux and Windows, plus the source: &lt;a href="https://github.com/msertdev/deadweight" rel="noopener noreferrer"&gt;github.com/msertdev/deadweight&lt;/a&gt;. It's free and MIT licensed.&lt;/p&gt;

&lt;p&gt;I'm curious what numbers other people get, especially how many of your skills have lost their descriptions. If deadweight misattributes something in your setup, issues are very welcome.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Update (v0.2.0):&lt;/strong&gt; A reader pointed out in the comments that MCP servers configured at user scope load in every project, even the ones that never use them. deadweight now counts MCP tool calls per project, and if a user-scope server is only used in one or two projects, it names them and tells you where in &lt;code&gt;.claude.json&lt;/code&gt; to move it. Thanks for the idea! Run &lt;code&gt;cargo install deadweight&lt;/code&gt; again to update.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>ai</category>
      <category>claude</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
