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

@dongnh311/claude-context-saver

v0.2.1

Published

MCP server that cuts Claude Code token usage. Two capabilities: log compression (build/test/install output) and smart file reading (AST-backed symbol-level source access). Context-efficient tooling for Pro-tier users.

Readme

@dongnh311/claude-context-saver

npm CI license

MCP server that cuts Claude Code token usage through two cooperating capabilities: (1) log compression for build/test/install output, (2) smart file reading for source code at the symbol level. Same philosophy: don't let raw, unfiltered content flood Claude's context — let Claude pull exactly what it needs.

Note: this package was originally published as claude-log-compressor (log side only). It has been renamed to @dongnh311/claude-context-saver now that file-side capabilities are landing. The old name is deprecated; please update your config (see Quick start).

Quick start

1. Add to your Claude Code MCP config at ~/.claude/mcp.json (or project .claude/mcp.json):

{
  "mcpServers": {
    "context-saver": {
      "command": "npx",
      "args": ["-y", "@dongnh311/claude-context-saver@latest"]
    }
  }
}

Or via CLI:

claude mcp add context-saver -s user -- npx -y @dongnh311/claude-context-saver@latest

2. Restart Claude Code. Tools smart_run, smart_build, smart_test, read_log_section show up now. File-side tools (smart_read, list_symbols, read_symbol, find_references_in_file, read_lines) ship in v0.2.0.

3. (Recommended) Nudge Claude in your project's CLAUDE.md:

## Token-efficient tooling (claude-context-saver)
- Build/test: use `smart_build` / `smart_test` instead of bash gradle/npm/jest/pytest.
- File reading (from v0.2): prefer `smart_read` over `Read` for source files > 300 lines.

Why

Two dominant sources of wasted tokens in a Claude Code session:

  • Noisy command output. gradle build, npm install, pytest can emit 5k–20k tokens per invocation, 90% of which is progress bars, deprecation warnings, and framework noise.
  • Whole-file reads for narrow questions. Claude reads a 2,000-line MainActivity.kt to fix one function; 90% of what goes into context is irrelevant.

Both compound quickly: the Pro 5-hour limit hits before the real work is done, prompt-cache hit rate drops, and the model's attention gets diluted.

How it works

Claude calls the MCP tool instead of bash/Read. The server runs the command (or parses the file), keeps the heavy output on disk, and returns only a compact summary plus an id Claude can use to retrieve detail on demand.

[Claude] ──► smart_build("./gradlew assembleDebug")
              │
              ▼
         [context-saver]
              │
              ├─► run command → 12k tokens raw
              │      │
              │      ▼
              │   classify → "gradle"
              │      │
              │      ▼
              │   gradle compressor (errors, deduped warnings, failing task)
              │      │
              │      ▼
              │   cache full log → ~/.cache/claude-context-saver/logs/grd_abc12345.log (7d TTL)
              │
              └─► return 0.8k token summary + log_id="grd_abc12345"
[Claude] ◄──

Same pattern for smart_read: parse file → return outline first, focused symbols on demand, cache AST for the session.

Tools — log side

| Tool | Input (highlights) | What it does | |---|---|---| | smart_run | command, cwd?, timeout_seconds?, max_output_tokens? | Runs any shell command, auto-classifies output, returns compressed summary + log_id. | | smart_build | tool? (gradle/npm/cargo/make/auto), args?, cwd? | Auto-detects build tool from cwd (gradlew, package.json, Cargo.toml, Makefile). | | smart_test | framework? (jest/pytest/junit/go/auto), pattern?, cwd? | Auto-detects test framework (go.mod, pytest config, package.json, gradlew). | | read_log_section | log_id, grep?, lines_around?, start_line?/end_line?, max_tokens? | Slice a cached full log. Escape hatch when compressed view isn't enough. |

Tools — file side

| Tool | Input | What it does | |---|---|---| | smart_read | path, focus?, mode? (outline/full/auto), max_tokens? | Smart replacement for Read. Returns outline first, focused symbols on demand. | | list_symbols | path, kinds?, depth? | Full symbol tree without bodies. | | read_symbol | path, names[] (dotted: Class.method), include_surrounding? | Return bodies of named symbols. | | find_references_in_file | path, identifier, context_lines? | AST-aware "where is X used inside this file" with inside_symbol annotation. | | read_lines | path, start_line, end_line | Line-range fallback when symbol approach doesn't fit. |

Languages supported for file side: Kotlin, Java, TypeScript/TSX, JavaScript/JSX, Python, Go, Rust. Swift deferred to a future release.

Benchmark — real Android project

Measured live on ./gradlew … against a real Android Compose + C++/NDK project (MasterCamera, 2 Gradle modules):

| Command | Raw tokens | Compressed | Reduction | |---|---:|---:|---:| | clean :app:assembleDebug | 2,090 | 82 | 96.1% | | clean :app:assembleRelease (R8) | 2,720 | 82 | 97.0% | | :app:installDebug → emulator | 955 | 3 | 99.7% | | :app:testDebugUnitTest | 780 | 82 | 89.5% | | :app:compileDebugKotlin (2 injected errors) | 667 | 114 | 82.9% ⟵ both errors with file:line:col preserved |

Average ≈ 93% reduction, 100% of errors and warnings kept.

Benchmark — real source files (file side)

Measured on actual Kotlin source from the same MasterCamera project:

| File | Lines | Full | smart_read outline | smart_read focus | Reduction (outline) | |---|---:|---:|---:|---:|---:| | CameraControl.kt | 1,040 | 7,949 | 839 | 1,261 (focus=startRecord) | 89.4% | | Camera2Control.kt | 951 | 8,721 | 878 | 893 (focus=captureImage) | 89.9% |

Both files cleared the SPEC §2 target ("≤20% of full-file tokens for a ≥1000-line Kotlin file"). Focused mode still beats 80% reduction because the outline gets bundled with the body.

Benchmark — synthetic fixtures (log side)

| Fixture | Kind | Original | Compressed | Reduction | |---|---|---:|---:|---:| | gradle-success.log | gradle | 1,005 | 64 | 93.6% | | gradle-failure.log | gradle | 1,708 | 173 | 89.9% | | jest-passing.log | jest | 242 | 34 | 86.0% | | jest-failing.log | jest | 578 | 363 | 37.2% | | junit-failing.log | junit | 827 | 151 | 81.7% | | npm-install-success.log | npm | 648 | 218 | 66.4% | | npm-install-fail.log | npm | 337 | 279 | 17.2% (info-dense) | | pytest-passing.log | pytest | 224 | 20 | 91.1% | | pytest-failing.log | pytest | 583 | 333 | 42.9% |

Run locally: npm run bench.

What each log compressor keeps / drops

Gradle

  • Keep: BUILD status + duration, every Kotlin/javac error with file:line:col, deduped warnings with occurrence counts ([×3]), failing task name, "What went wrong" block.
  • Drop: > Task :xxx UP-TO-DATE/NO-SOURCE, Download … URLs, Daemon startup chatter.

npm / yarn / pnpm

  • Keep: npm ERR! blocks with error code, added X packages, deduped deprecations (per package, top 10), audit summary.
  • Drop: duplicate deprecation lines, download progress, boilerplate audit text.

Jest / Vitest

  • Keep: Test Suites: / Tests: / Time: summary, every ● Test › name failure block with assertion diff.
  • Drop: PASS src/… names (collapsed to count), duplicated "Summary of failing tests" block.

Pytest

  • Keep: platform header, ERRORS: + FAILURES: blocks verbatim, short summary info, final result line.
  • Drop: progress dot lines (tests/foo.py ...... [10%]), rootdir/plugin chatter.

JUnit (Gradle/Maven test output)

  • Keep: each FAILED test with FQCN + assertion + app stack frames, total count.
  • Drop: PASSED names (count only), framework frames (org.junit.*, java.base/jdk.internal.*, kotlinx.coroutines.internal.*, android.os.*, reflection).

Generic (fallback)

  • Keep: every line matching /error|fail|exception|fatal|panic/i.
  • Transform: consecutive identical lines deduped, middle-truncated when over budget.

FAQ

What if the compressor drops something I need? Every response includes log_id. Call read_log_section with a grep pattern or start_line/end_line. Full log is on disk for 7 days.

Does it work on Windows? WSL only in v0.1/v0.2. Native Windows is Phase 3.

Does it send anything to a server? No. Commands run locally, logs live on your disk, nothing phones home.

Will Claude actually use smart_* instead of bash? With the CLAUDE.md snippet in Quick start, yes. Tool descriptions also explicitly say "ALWAYS prefer this". In practice adherence is high.

Why a scoped package name (@dongnh311/…)? The plain claude-context-saver unscoped name was already taken by an unrelated package. Scoped keeps the descriptive name.

Development

npm install
npm run typecheck
npm test           # vitest
npm run bench      # compressor benchmark table
npm run build      # tsc → dist/index.js (+ shebang + chmod)
npm run dev        # tsc --watch
npx @modelcontextprotocol/inspector node dist/index.js   # manual tool exercise

Layout, conventions, milestones: see CLAUDE.md. Unified implementation spec: SPEC.md. Archived log-only spec: SPEC-v0.1.md. High-level pitch: spec-overview.md.

Links

License

MIT