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

contextsnap

v2.3.0

Published

Generate a token-optimized context snapshot of your codebase utilities and copy it to your clipboard — instantly.

Readme

Contextsnap

Generate a token-optimized context snapshot of your codebase utilities and copy it to your clipboard — in one command.

npm version License: MIT Node.js


The Problem

When you vibe-code with an LLM (Claude, ChatGPT, Gemini), you paste a prompt and it writes a helper function from scratch — even though your codebase already has one in src/utils/. The result: duplicate code, subtle bugs, and hours of debugging.

The Fix

Run contextsnap against your utilities folder. It scans your exports, strips implementation bodies, and copies a token-optimized context snapshot straight to your clipboard. Paste it into your LLM and get code that actually reuses what you already have.

  [Contextsnap] ─────────────────────────────────────────
  ├── date.ts (parseISO, formatLocal, diffDays)
  ├── currency.ts (formatUSD, getExchangeRate)
  └── theme.ts (colors, breakpoints)
  ───────────────────────────────────────────────────────
  ✔ Copied to clipboard! (~1,420 tokens)

Install

Use without installing (recommended)

npx contextsnap src/utils

Install globally

npm install -g contextsnap
contextsnap src/utils

Usage

contextsnap [directory ...] [options]

Arguments

| Argument | Description | |---|---| | [directory ...] | One or more folders to scan (e.g. src/utils src/hooks). If omitted, contextsnap auto-detects the first of: src/utils, src/lib, src/helpers, utils, lib, src |

Options

| Flag | Description | |---|---| | --clipboard-only | Skip writing .ai-context.md to disk; clipboard only | | --stdout | Print markdown to stdout for piping (no clipboard, no file) | | --watch | Re-run automatically on every file change. Press Ctrl+C to stop | | --format=<fmt> | Output format: markdown (default) or json | | --ignore=<pattern> | Skip folders/files matching <pattern> — whole-name match, * wildcards supported (repeatable) | | --budget=<tokens> | Fit the snapshot under a token ceiling — trims the least-imported exports first | | --dupes | Report likely duplicate exports (formatDate vs dateFormat); exit 1 when any found | | --inject[=<file>] | Write the snapshot between <!-- contextsnap:start/end --> markers in CLAUDE.md / AGENTS.md (or <file>) — every AI session picks it up automatically | | --check | Exit 1 if the committed snapshot (.ai-context.md, or the injected block with --inject) is stale — use in CI like a lint step | | --mcp | Start an MCP stdio server for Claude Desktop / Claude Code / Cursor | | -h, --help | Show help with examples |

You can also set persistent defaults in a .contextsnaprc.json file (see Config file).

You can also put ignore patterns in a .contextsnapignore file (one per line, # for comments).

Examples

# Zero-config: auto-detect your utils folder
contextsnap

# Scan utils folder, copy to clipboard, save .ai-context.md
contextsnap src/utils

# Scan entire src directory, clipboard only
contextsnap src --clipboard-only

# Scan multiple folders at once
contextsnap src/utils src/hooks

# Skip test files and mocks
contextsnap src --ignore=__tests__ --ignore=*.mock.*

# Pipe or redirect the markdown anywhere
contextsnap src --stdout > context.md

# Live refresh — re-runs every time you save a file
contextsnap src/utils --watch

# Machine-readable JSON output
contextsnap src/utils --format=json --stdout | jq '.files[].path'

# Start MCP server (used by Claude Desktop / Claude Code / Cursor)
contextsnap --mcp

# Use via npx without global install
npx contextsnap src/utils

MCP Server Mode

The easiest way to use contextsnap — your AI gets codebase context automatically, no copy-paste needed.

contextsnap --mcp starts a Model Context Protocol stdio server. Claude Desktop, Claude Code, and Cursor can call it as a tool directly.

Setup: Claude Desktop

Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):

{
  "mcpServers": {
    "contextsnap": {
      "command": "contextsnap",
      "args": ["--mcp"]
    }
  }
}

Restart Claude Desktop. The get_context tool will appear. Just ask:

"What utility functions does this project already have?"

and Claude will call get_context automatically to scan your codebase.

Important — Claude Desktop starts MCP servers in / or your home directory, not your project. Tell Claude your project path once ("my project is at /Users/me/dev/myapp") and it will pass it via the tools' root parameter. Project-scoped hosts (Claude Code, Cursor) start the server in the project directory, so root is unnecessary there.

Setup: Cursor / other MCP-compatible tools

{
  "mcpServers": {
    "contextsnap": {
      "command": "npx",
      "args": ["contextsnap", "--mcp"]
    }
  }
}

MCP Tools

get_context — full snapshot of every export.

| Parameter | Type | Description | |---|---|---| | dirs | string[] (optional) | Directories to scan. Defaults to auto-detect. | | ignore | string[] (optional) | Patterns to skip (e.g. ["__tests__", "*.mock.*"]) |

search_exports — find an export by name, signature, or JSDoc substring. Returns file:line locations so the agent can jump straight to a definition. Use before writing a new utility to check whether one already exists.

| Parameter | Type | Description | |---|---|---| | query | string | Case-insensitive substring to match | | dirs, ignore | optional | Same as get_context |

get_file_context — signatures, line numbers, and JSDoc for a single file. Much cheaper than get_context when the agent already knows the file.

| Parameter | Type | Description | |---|---|---| | path | string | File path relative to cwd |


Inject Mode — context in CLAUDE.md, zero paste

contextsnap src --inject writes the snapshot between markers in your CLAUDE.md (or AGENTS.md — auto-detected, or any file via --inject=<file>):

# My project rules          ← your content, never touched

<!-- contextsnap:start -->
# CONTEXTSNAP CODEBASE CONTEXT …
<!-- contextsnap:end -->

Every Claude Code / agent session loads it automatically — no clipboard, no MCP setup. Re-running replaces only the marker block; idempotent. Combine with --watch to keep it fresh on every save. Set "inject": true (or a filename) in .contextsnaprc.json to make it the default.


Token Budget — fit any context window

contextsnap src --budget=2000 trims the snapshot toward a token ceiling. contextsnap counts how many files import each export across your project (only imports that actually resolve to the scanned files — bare npm packages never inflate a rank) and trims the least-imported exports first, so the utilities your code leans on survive. A summary reports what was trimmed.

Token counts are estimated at ~4 characters/token; real tokenizers vary, so treat the ceiling as a close target, not an exact guarantee. --budget also raises the scan cap from 300 to 5,000 files — it exists precisely for big repos.


Duplicate Detector — find drift before your AI adds more

contextsnap src --dupes flags exports that look like the same utility written twice:

⚠ 1 likely duplicate export pair(s):
  • dateFormat (core/src/dates.ts:2) ≈ formatDate (ui/src/button.ts:3) — same words, different order

Catches identical names in different files and same-word/different-order names (formatDate vs dateFormat). Exits 1 when any are found, so it slots into CI next to --check.


Monorepo Awareness

In npm/yarn/pnpm workspaces, import hints for files in other packages use the package name instead of a brittle relative path:

// import from '@acme/ui'        ← not '../../packages/ui/src/button'

Auto-detected from package.json workspaces or pnpm-workspace.yaml — no configuration.


Check Mode — CI drift guard

contextsnap src --check regenerates the snapshot in memory and compares it against the committed one (.ai-context.md, or the injected block when combined with --inject). Generation dates are ignored; exit 1 on drift:

# .github/workflows/context.yml
- run: npx contextsnap src --check   # fails the build when the snapshot is stale

Watch Mode

contextsnap src/utils --watch runs the pipeline once immediately, then re-runs whenever any .js/.ts/.jsx/.tsx file changes. Your .ai-context.md stays fresh automatically.

contextsnap src/utils --watch
# [Contextsnap] ✔ Copied to clipboard! (~1,420 tokens)
# ℹ Watch mode active — re-running on file changes. Press Ctrl+C to stop.
# [Contextsnap] Refreshed at 2:34:07 PM
# [Contextsnap] Refreshed at 2:41:22 PM

Works on macOS, Windows, and Linux (Node ≥18).


Config file

Create .contextsnaprc.json in your project root to set persistent defaults. CLI flags always override.

{
  "dirs": ["src/utils", "src/hooks"],
  "ignore": ["__tests__", "*.mock.*"],
  "format": "markdown",
  "clipboardOnly": false
}

| Key | Type | Description | |---|---|---| | dirs | string[] | Default directories to scan | | ignore | string[] | Default ignore patterns | | format | "markdown" | "json" | Output format | | clipboardOnly | boolean | Don't write .ai-context.md | | stdout | boolean | Print to stdout | | inject | boolean | string | Always inject into CLAUDE.md/AGENTS.md (or the given file) | | budget | number | Default token ceiling (same as --budget) |


GitHub Action

Auto-commit .ai-context.md on every push so your team always has a fresh snapshot:

# .github/workflows/context.yml
name: Update context snapshot
on: [push]
jobs:
  snapshot:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: myothuko98/contextsnap@v2
        with:
          dirs: 'src/utils src/hooks'
          ignore: '__tests__'
      - run: |
          git config user.name "contextsnap-bot"
          git config user.email "[email protected]"
          git add .ai-context.md
          git diff --staged --quiet || git commit -m "chore: update context snapshot [skip ci]"
          git push

Action inputs

| Input | Description | |---|---| | dirs | Space-separated directories to scan | | ignore | Space-separated ignore patterns |

Action outputs

| Output | Description | |---|---| | context-file | Path to the generated file (always .ai-context.md) | | token-estimate | Approximate token count |


What it does

  1. Scans the target directory recursively for .js, .ts, .jsx, .tsx files
  2. Extracts exported function/const/let/var/class/interface/type/enum signatures, export default (declarations and expressions), export { ... } / export type { ... } lists, export * [as ns] from, CommonJS module.exports, and JSDoc blocks
  3. Strips implementation bodies — only the contract (name, params, return type) is kept
  4. Validates extraction against es-module-lexer: any ESM export the fast parser misses is still emitted as a name-only stub, with a warning — so the context never silently omits an export
  5. Compiles a token-optimized markdown file with reuse instructions for the AI and per-file import hints
  6. Copies it to your clipboard automatically (pbcopy / xclip / clip)
  7. Prints a retro-green ASCII tree of everything scanned

Known limitations

  • TypeScript generics with inline object constraints (function f<T extends { a: string }>()) may truncate the signature at the {.
  • Decorators are not included in extracted signatures.
  • The es-module-lexer validation pass is best-effort on TypeScript files (it is a JS ESM lexer); it fully covers .js/.mjs/.jsx.

Output format

The clipboard and .ai-context.md file look like this:

# CONTEXTSNAP CODEBASE CONTEXT (Generated 2026-07-03)

> **Instructions for the AI assistant:** The utilities below ALREADY EXIST
> in this project. When writing code, import and reuse them instead of
> re-implementing anything.

## File: date.ts
​```typescript
// import from './date'

/**
 * Formats an ISO string to a human-readable local date.
 * @param isoString - The ISO date string to convert
 */
export function formatLocal(isoString: string): string; // :12

export const DEFAULT_LOCALE: string; // :4
​```

Use --format=json for structured output:

{
  "generated": "2026-07-03",
  "stack": ["react", "zod"],
  "files": [
    {
      "path": "date.ts",
      "importFrom": "./date",
      "exports": [
        { "name": "formatLocal", "type": "function", "signature": "export function formatLocal(isoString: string): string;", "line": 12 }
      ]
    }
  ]
}

How to use with an LLM (manual mode)

  1. Run contextsnap src/utils
  2. Open your LLM (Claude, ChatGPT, Gemini, etc.)
  3. Press Cmd+V / Ctrl+V to paste the context
  4. Write your prompt: "Write a checkout form component using the zip validator from context."
  5. Get code that actually uses your existing utilities

Or use MCP mode and skip steps 1–3 entirely.


Platform support

| Platform | Clipboard command | |---|---| | macOS | pbcopy | | Linux | xclip or xsel | | Windows | clip |

If clipboard copy fails, the tool warns you and falls back to .ai-context.md.


Development

git clone https://github.com/myothuko98/contextsnap.git
cd contextsnap
npm install
npm test

Tests use Vitest.


Scope limits

  • Ignores node_modules, .git, and hidden files automatically
  • Exits with a warning if the target folder contains >300 files (narrow your path)
  • Read-only — never modifies your source files

License

MIT © 2026 myothuko98