npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@bouncei/tokenlens

v0.0.1

Published

See exactly what's eating your Claude Code context window — and stop it.

Downloads

195

Readme

tokenlens

ci license Node.js

See exactly what's eating your Claude Code context window — and stop it.

npx -y github:bouncei/tokenlens status

That's the install. No clone, no build, no config.


Why this exists

Claude Code's built-in /context is documented to undercount MCP overhead by ~40k tokens per session. Anthropic was asked to fix it in March 2026 and closed the issue as "not planned." That's the wedge: the vendor's interest is to keep token consumption opaque to maximize per-user revenue; yours is to see exactly where your $200/mo Claude Max budget goes.

tokenlens is aligned with your wallet, not theirs.

What you actually see

Run against my live session as I'm writing this:

$ tokenlens status
tokenlens status
  session  ~/.claude/projects/-Users-josh-tokenlens/abc.jsonl
  turns    278 assistant

Tokens consumed by Anthropic
  input (uncached)           38.9k
  cache writes               2.07M   ← bloat lives here
  cache reads               41.21M   ← cheap
  output                    298.4k
  cache hit rate             95.2%

Output by attributionSkill
  <unattributed>          ████████████████   208.7k   (213 turns)
  idea-scout              ██████░░░░░░░░░░    92.6k   (65 turns)

Injected context by source
  cache_invalidation_or_growth  ████████████████ ! 520.3k   across 16 turns
  deferred_tools_added          █░░░░░░░░░░░░░░░ ~  25.0k   3 ev, 0 B text
  skill_listing                 ░░░░░░░░░░░░░░░░     1.5k   1 ev, 13.3 KB text
  hook_additional_context       ░░░░░░░░░░░░░░░░      791   1 ev, 5.5 KB text

MCP servers (loaded vs. invoked)
  (~50.5k estimated on tools never called)
  7dfd9fcf…               ████████████ ~  10.3k   ● never called
  plugin_playwright_playw…███████░░░░░ ~   5.8k   ● never called
  playwright              ███████░░░░░ ~   5.8k   ● never called
  Claude_in_Chrome        ██████░░░░░░ ~   5.5k   ● never called
  filesystem              ████░░░░░░░░ ~   3.5k   ● never called
  memory                  ███░░░░░░░░░ ~   2.3k   ● never called
  ...
  202 dead tools (use --show-dead for full list)

Two findings worth the install on their own:

  1. ~50,500 tokens of context overhead this session was spent on MCP tools that were never invoked. Every server I had loaded — filesystem, memory, playwright, all 10 of them — got definition-injected and never called. That's /context reporting "you're at 60%" while 25% of the load is dead weight you could disable with one line in .mcp.json.

  2. 520k tokens were written to cache as part of TTL-expiry invalidations across 16 separate moments — roughly $4 of cache-write cost on Opus, paid silently across the session and invisible to /context. tokenlens names it as cache_invalidation_or_growth so you can see when it's happening.

Commands

tokenlens status

One-shot breakdown of the active session. Reports Anthropic's exact per-turn usage from message.usage, attribution by attributionSkill, and a share-by-weight breakdown of which injected sources contributed to cache writes. A separate cache_invalidation_or_growth bucket captures cache writes that can't reasonably be tied to any visible attachment.

Flags:

  • --cwd <path> — resolve the active session for a different working directory
  • --session <file> — read a specific .jsonl directly

tokenlens watch

Same view as status, refreshed live as the session log grows. Useful to keep open in a side terminal while you work.

tokenlens watch

Press ctrl-c to stop.

tokenlens doctor

Detects (and optionally fixes) the two pathologies most commonly responsible for hidden context growth per Issue #29971:

  1. Stale plugin versions~/.claude/plugins/cache/<source>/<plugin>/ directories still holding previous versions of installed plugins.
  2. Duplicate skill symlinks~/.claude/skills/ symlinks pointing to the same canonical target, doubling injection of the same skill.

Default is dry-run; pass --fix to actually remove. Every deletion is logged with full path, and the tool refuses to touch anything outside ~/.claude/.

tokenlens doctor          # report only
tokenlens doctor --fix    # actually delete

tokenlens init and tokenlens budget (v2 preview)

Configure a weekly token budget and check your current session against it:

tokenlens init --tier max5      # writes ~/.claude/tokenlens.json with sane defaults
tokenlens budget                # shows: ALLOW / WARN / ASK / DENY vs your budget

These are the building blocks for v2's PreToolUse hook — see "v2 preview" below.

v2 preview — proactive budget enforcement (testable today)

The next surface is a Claude Code plugin that runs on every tool call and:

  • Silently allows if you're under 50% of your weekly cap
  • Injects a warning into Claude's context at 50–80% (Claude can decide to wrap up early)
  • Asks for confirmation at 80–95% (you click through)
  • Denies at 95%+ (or earlier if hardCap: true in your config)

It's already wired up. Test it locally:

git clone https://github.com/bouncei/tokenlens.git
cd tokenlens
pnpm install                                # builds dist/
tokenlens init --tier max5                  # writes ~/.claude/tokenlens.json
claude --plugin-dir ./tokenlens-cc          # loads the plugin

Now every tool call hits the budget evaluator. Watch the decisions in ~/.claude/tokenlens.log. The PreToolUse hook contract is fail-allow — a misbehaving hook will never block your workflow.

Marketplace submission to claude-plugins-community is pending.

How it works

tokenlens reads ~/.claude/projects/<encoded-cwd>/<session-uuid>.jsonl. The session log already contains Anthropic's ground-truth per-turn token counts, so for past turns tokenlens reports exact numbers — not estimates.

Each line is a JSON object representing one event in the session. The relevant fields:

  • type: "assistant" rows contain message.usage: Anthropic's exact per-turn token count (input, cache_creation, cache_read, output, including the ephemeral_5m vs ephemeral_1h cache split).
  • attributionSkill on each assistant row identifies which skill Anthropic attributed the turn to.
  • type: "attachment" rows include the literal content of injected skills, hook context, todo reminders, and MCP-server tool deltas.

We aggregate these, share-out each turn's cache_creation across the attachments that preceded it (weighted by tokenized content size, or a heuristic for text-less injections), and cap per-event attribution at 1.5× weight so cache invalidations don't get falsely pinned on whatever attachment happened to be most recent.

Full schema notes in docs/SCHEMA.md.

Install (other paths)

The fastest install is npx, but if you want a stable binary on $PATH:

# Globally
pnpm add -g github:bouncei/tokenlens
# or
npm install -g github:bouncei/tokenlens

# From source
git clone https://github.com/bouncei/tokenlens.git
cd tokenlens
pnpm install      # also builds dist/ via the prepare script
./dist/index.js status

Once published to npm:

npx tokenlens status

Requires Node.js 20 or newer.

Roadmap

  • v1 (shipped, v0.1.0): CLI status, watch, doctor, init, budget. Free, OSS.
  • v2 (in progress, testable now): tokenlens-cc plugin wiring tokenlens into Claude Code's PreToolUse hook — proactive budget warnings, hard caps, and session-context injection. Pending community marketplace review. Free tier stays free; paid tier ($9–19/mo) adds cross-machine sync, weekly digest, team views (not yet built).
  • v3 (next 12 months): Same value prop, cross-IDE. Cursor, Cline, Gemini CLI.

See DESIGN.md for the architecture overview.

Caveats

  • Reverse-engineered against Claude Code v2.1.138 (May 2026). The session jsonl schema may shift on subsequent versions; tokenlens preserves unknown fields and won't crash on them.
  • The local tokenizer (@anthropic-ai/tokenizer) tracks the Claude 2 era. Estimates for content we tokenize locally are ±5% vs. server-side counts. Past-turn numbers from message.usage are exact.
  • The cache_invalidation_or_growth bucket lumps together genuine cache TTL expirations and conversation growth — tokenlens can't yet distinguish them without more session signal. Working on it.

Contributing

Issues and PRs welcome. The project is small and the surface is well-bounded — start with docs/SCHEMA.md to understand the session jsonl format, then CONTRIBUTING.md for how to add a new attachment category or analyzer.

If your ~/.claude/ has a structure tokenlens doesn't recognize, please open an issue with a sample line (anonymized) — every new attachment type we map deepens the wedge.

License

MIT — see LICENSE.