Dev.to · 6 min read

I measured what my Claude Code setup costs on every request. Most of my skills had gone blank.

I measured what my Claude Code setup costs on every request. Most of my skills had gone blank.

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. 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. 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. Where the numbers come from Claude Code writes a transcript of every session to ~/.claude/projects//.jsonl. Besides the conversation, it records what was loaded at startup as separate entries: skill_listing: every skill name and description the model is shown deferred_tools_delta: the names of all deferred tools, including every MCP tool, plus MCP servers that failed to connect mcp_instructions_delta: instruction blocks MCP servers inject agent_listing_delta: the subagent types on offer hook_success: output of your SessionStart hooks, which often lands in context And for each API call, the assistant entry carries the real usage: "usage": { "input_tokens": 2, "cache_creation_input_tokens": 40260, "cache_read_input_tokens": 34273 } 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. The finding: past ~30,000 characters, your skills go blank When I opened the skill_listing entry, most lines looked like this: - some-plugin:some-skill - another-skill - yet-another:skill No description. Just names. 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, 220 of 283 skills were listed by name only. In an older session with 672 skills installed, 642 had no description. Why that matters: the description is how the model decides when to use a skill. A bare name like review or start tells it almost nothing. So every skill you installed "just in case" isn't only costing tokens. It's pushing out the descriptions of the skills you actually rely on. 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. What else was in there Once everything was attributed to where it came from, a few other things showed up: MCP servers that failed to connect at startup, every session, for weeks. 36 MCP servers I had never signed in to, each still listing its authenticate and complete_authentication tools. Duplicate skills: the same skill name shipped by two different plugins. One skill whose description alone cost about 3,000 tokens per request. I had used it once. And the obvious one: 272 of 283 skills hadn't been used in 30 days. deadweight I turned all of this into a CLI called deadweight. It reads the same transcripts and prints: $ 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. (That's an illustrative example; your output will be your own setup.) How it works: Measure: the total is the billed size of the first request in your latest session. Attribute: 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 hooks.json. Check usage: every transcript from the last 30 days, subagents included, is scanned for Skill calls, MCP tool calls, agent launches and slash commands. Then deadweight fix disables unused plugins and moves unused skills aside, and deadweight undo puts everything back. Making "fix" safe A tool that edits your config needs to be boring and predictable: Read-only by default. Only fix and undo write, and both ask first. Nothing is deleted. Plugins are set to enabledPlugins: false in settings.json, not uninstalled. Skills are moved into a backup folder. Everything is backed up. Each run writes a manifest and a copy of settings.json to ~/.claude/deadweight/backups//. Plugins with hooks are skipped. A memory or safety plugin can do useful work without ever showing up as "used", so those need --include-hooked. It refuses with too little history. With fewer than 5 sessions, "unused" doesn't mean much. No secrets, no network. From .claude.json it only reads MCP server names, never commands, env vars or headers. A test asserts that secret values never reach the output. Built in Rust, with Claude Code deadweight is a single Rust binary. Transcripts get big (mine were 1.4 GB), so files are scanned in parallel with rayon, 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. 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 ~/.claude directory. The tests caught a real bug early: skill names like plugin:skill were being split on the wrong colon, which silently gave one skill's size to its neighbour. Caveats The total is measured. The per-item breakdown is estimated from text length, since there's no local tokenizer. Claude Code deletes transcripts after cleanupPeriodDays (30 by default), so "unused" can only look that far back. Use --keep for things you use rarely. The ~30k-character listing limit is what I observed, not documented behaviour. Try it cargo install deadweight deadweight Prebuilt binaries for macOS, Linux and Windows, plus the source: github.com/msertdev/deadweight. It's free and MIT licensed. 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.

This is a summary aggregated from Dev.to. Read the complete article on the original site:

Read full article at Dev.to

More AI & Machine Learning News