I have a lot of skills and MCP servers installed in Claude Code. They accumulate. You install a skill to try it once, you add an MCP server for some integration you needed that week, and then you move on, and none of it ever leaves.

Here's the part I hadn't thought about: every one of those is loaded into the context window on every single turn. Skill descriptions, subagent definitions, MCP tool schemas. They're all sitting in the prompt before I've typed a single word. And most of them I never use. They were eating my context silently, in the background, for no purpose at all.

So I built context-introspect, a skill that turns Claude's attention inward and audits its own setup.

The gap

Claude Code already gives you /context (which shows a total) and /usage (which shows the current session). But neither answers the question that actually matters: which of this stuff have I not touched in weeks, and what is it costing me? I wanted something that looked at my real history and told me, honestly, what was dead weight, and then helped me get rid of it.

What it does

You ask Claude "audit my context." It scans your actual session history, works out how often each skill, subagent, and MCP server has really been invoked (and when you last used it), weighs that against what each one costs in tokens, and hands you a verdict: keep, cut, or review.

Then, the part I cared about most: it can take action. It will reversibly disable the dead weight for you. Not delete. Disable. Every item is moved aside, and the exact undo command is printed right next to it. A tool whose entire job is telling you what to remove should never be able to lose your data. So I made it physically incapable of it.

What I decided early

Three choices shaped the whole thing, and I'd make each one the opposite way for a human-facing tool:

Real usage, not guesses. It reads your session transcripts and counts actual invocations, tallied across all your projects, so it never tells you to cut something you lean on in another repo. "Unused" means unused everywhere I can see.

Honest about what it estimates. Token figures are estimates, labelled as such. The default audit won't guess an MCP server's price; it flags unused servers by usage instead. But there's an opt-in pass that measures the real number (more on that below).

Reversible, never destructive. Disable, with an undo. Always.

The hurdle: the audit tool that bloated the thing it was auditing

The first version embarrassed me, and it's worth telling because the fix became the whole architecture.

I'd had the script dump everything it found as one big blob of JSON (every skill, every server, every field), and Claude would read all of it back in to write the report. It worked. But the output was about 30KB. Which means: to produce a report about context bloat, Claude was loading 30KB of JSON into the very context window I was trying to shrink. The tool was the disease. The cure was counterproductive.

So I split it in two. A small Python script does the heavy lifting. It reads the megabytes of transcripts, crunches the usage, decides the verdicts, and emits a tiny, pre-digested summary of a few KB. Claude only ever sees that summary and reasons over it. The script crunches; the agent advises. Auditing your context stopped costing you context.

~/.claude transcripts + config megabytes of session JSONL raw analyze.py: the cruncher reads, tallies, decides verdicts locally stdlib emits a few KB, not 30KB compact digest totals · cut · review · kept ~4KB Claude reasons & advises report + reversible disable, never the raw data
The script does the heavy reading so the agent never has to, auditing context without bloating it.

What I took from Karpathy

I didn't invent the principles behind this. Andrej Karpathy laid out a set of guidelines for working with coding agents, the ones that turned into that CLAUDE.md half of GitHub is now running. I read back through them and pulled out the few that mattered most for a tool like this:

Simplicity first. The whole thing is one Python file (standard library only, nothing to pip install) and one Markdown instruction file. That's the entire skill.

Think before you act. Verify your assumptions instead of charging ahead. That's exactly the cross-project-safety rule (never flag something you use elsewhere) and the measured-vs-estimated honesty: the tool refuses to state a guess as a fact.

Surgical changes. Touch only what's confirmed, and only that. The disable step never moves anything you didn't explicitly approve, and it's all reversible.

I took the highest-leverage ideas from the way he approaches skills and applied them here. Credit where it's due. The discipline is his; I just pointed it at a different problem.

How I built it

scripts/analyze.py is pure Python standard library. It reads ~/.claude/projects/*/*.jsonl (your session transcripts), tallies tool calls per skill, subagent, and MCP server across every project, estimates token cost, and prints the compact digest. SKILL.md is the set of instructions Claude follows: run the script, reason over the digest, present the report, offer the reversible disable.

It ships as a Claude Code plugin, and the repo doubles as its own marketplace, so installing it is two lines:

/plugin marketplace add catancs/context-introspect
/plugin install context-introspect@catancs

Then you just ask Claude to audit my context.

What happened when I ran it on myself

On my own machine it found three MCP servers I'd never once called: filesystem and memory (both redundant, since Claude Code has native file tools and my memory lives in plain Markdown files, not the memory MCP's graph), and monday, which I just never use from the agent. It also turned up a pile of project skills and subagents I'd stopped using weeks ago. I disabled the three servers in one go. Reversibly, of course.

It also caught me in a lie my own headline was telling: an early version over-counted what you could "reclaim" by including plugin-managed skills it couldn't actually disable. Running it on real data is what exposed that. Clean unit tests never would have. So the honest version reports a smaller, truer number and tells you the rest is reclaimable only by uninstalling the plugin. I'd rather under-promise.

What I built next

When I first wrote this, the honest gap was that it couldn't measure the exact per-turn cost of an MCP server. Those tool schemas are usually the heaviest thing in your context, easily thousands of tokens each, but the number doesn't live on disk; it only exists once the server is running. So I built it: an opt-in pass that briefly launches each stdio server, does the MCP handshake, asks for its tool list, and counts the real tokens. On my own machine it clocked one server at 1,171 tokens, every single turn, for two tools I almost never use. That's the whole difference between "you have a server called X" and "X is costing you 1,171 tokens a turn." Only the second one makes you do anything about it.

Why I'm sharing this

My setup had quietly turned into thousands of tokens of things I don't use, loaded on every single turn, and nothing would tell me. If you live in Claude Code, you almost certainly have the same blind spot. It's open source, it's reversible, and it takes one command to try.

The code is on GitHub.