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

stapes-context-trim

v0.1.2

Published

Strip a codebase to the essentials for an AI prompt. Respects .gitignore. Skips node_modules, lockfiles, binaries, build output. One command, no install, no cloud, no API key. Stable --json summary for AI agents. Tested on Node 24.

Readme

stapes-context-trim

AI coding assistants have token budgets. Your codebase does not. Every time you paste a repo into a chat you fight the model context window — node_modules, lockfiles, binaries, build output, all of it.

stapes-context-trim walks the tree, respects .gitignore, skips the noise, and emits one Markdown digest. One command. No cloud. No config. No API key. No telemetry. Runs offline.

Why

The standard pattern is "copy the repo and paste it." That works on a 200-file project. It fails on a 5,000-file monorepo — the model truncates the middle of the prompt, and what it keeps is the boilerplate.

stapes-context-trim is one command that gives the model only what it needs. Runs locally, in milliseconds, on any tree. The output is a single Markdown file with one fenced block per source file, ordered, truncated predictably.

This is for the moment before the paste — the part where the prompt becomes too long, the model starts losing context, and you start deciding which files to include. The tool removes that decision.

How

npx stapes-context-trim                # scan ., write Markdown to stdout
npx stapes-context-trim . --out ctx.md # write to a file
npx stapes-context-trim . --json       # structured summary, agent-friendly
npx stapes-context-trim . | pbcopy     # macOS — straight to clipboard
npx stapes-context-trim . | xclip      # Linux

What you get on a small repo:

# Codebase Context: cttest

Generated by stapes-context-trim v0.1.1
Root: `/private/tmp/cttest`
Files: 3
Bytes: 93

---
## .gitignore
```
node_modules/
```
## package.json
```json
{"name":"demo","version":"0.0.1","type":"module"}
```
## src/util.ts
```ts
export const foo = () => 42;
```

---

End of digest.

Each file becomes a section with a heading (## <relative path>) and a fenced code block. The fence length is picked to be strictly greater than the longest run of backticks in the body so embedded ``` blocks inside a source file do not terminate the outer fence (CommonMark-compliant). The fence is followed by a language hint inferred from the file extension: .tsts, .pypython, .jsonjson, and so on. If a file body exceeds --per-file-chars, the renderer truncates it and appends a marker line:

[truncated: original 12450 chars, showing 49980]

The number after showing is the exact number of source characters emitted before the marker (not the configured cap). When the running total exceeds --max-total-chars, the digest stops and adds:

---

End of digest.

Pipe that into a chat, save it as AGENT_CONTEXT.md, or feed it to a script.

The --json shape (for agents):

{
  "tool": "stapes-context-trim",
  "version": "0.1.1",
  "root": "/Users/you/my-project",
  "fileCount": 247,
  "totalBytes": 482103,
  "elapsedMs": 41,
  "skipped": {
    "binary": 18,
    "lockfile": 12,
    "tooLarge": 3,
    "gitignored": 4128
  },
  "fileList": [
    { "path": "src/index.ts", "size": 412, "lines": 18 },
    { "path": "src/util.ts", "size": 89, "lines": 4 }
  ]
}

That tells an agent what was considered and what was dropped, without forcing it to parse the full Markdown. Each entry in fileList is an object with path (relative path from the scan root), size (bytes on disk), and lines (LF line count).

What

| Flag | Default | Effect | |---|---|---| | [path] | . | directory to scan | | --out <file> | stdout | write digest to file | | --max-file-bytes N | 204800 (200 KB) | skip files above N bytes | | --per-file-chars N | 50000 | truncate each file body at N chars | | --max-total-chars N | 800000 | stop emitting once digest hits N chars | | --follow-symlinks | false | follow symlinks (off by default) | | --verbose | false | log progress to stderr | | --json | false | emit JSON summary instead of Markdown | | --version | — | print version | | --help | — | print help |

What it skips (in addition to .gitignore):

Always-excluded directories (matched at every depth):

  • node_modules/
  • .venv/
  • .next/, .nuxt/, .turbo/, .vercel/, .vite/
  • .cache/, __pycache__/
  • dist/, build/, out/, target/, coverage/, vendor/
  • .claude/, .playwright-mcp/ (AI-tool config dirs)
  • .git/, .svn/, .hg/ (VCS metadata)

Minified assets: any file whose name ends in .min.js or .min.css (case-insensitive).

Named lockfiles (exact filename match at any depth):

  • package-lock.json
  • pnpm-lock.yaml
  • yarn.lock
  • bun.lock, bun.lockb
  • Cargo.lock
  • composer.lock
  • Gemfile.lock
  • Pipfile.lock
  • poetry.lock
  • uv.lock
  • go.sum

Only the exact names above are skipped. Custom or generated lockfiles that do not match a name in this list are not filtered by name — they are caught by .gitignore or by the size limit if applicable.

Other:

  • Binary files (NUL byte in the first 8 KB)
  • Empty files (size === 0)
  • Files above --max-file-bytes (default 204800 / 200 KB)
  • Symlinks (unless --follow-symlinks); with --follow-symlinks, every link target is realpath-checked against the scan root and rejected if it escapes
  • Files whose extension is not in the recognised text set. The set includes common code, config, markup, and build-file names (.ts, .js, .py, .json, .md, .yaml, .sh, Dockerfile, Makefile, …). Anything else is dropped on extension alone, before the content sniff runs.

.gitignore is honoured at every directory level. Nested .gitignore files apply to files at their depth and below, matching the ignore-library semantics.

The output is fenced with language hints inferred from file extension (.tsts, .pypython, etc.).

Agent-native

This tool is designed for AI agent runtimes and CI scripts:

  • Zero telemetry. No network calls. No analytics. No update checks.
  • Zero config. No files to write. No env vars to set. No install step.
  • --json emits parseable output with stable fields (tool, version, root, fileCount, totalBytes, elapsedMs, skipped.*).
  • Exit codes are stable. 0 clean, 1 invalid args (unknown flag, unparseable number), 2 Node.js below the supported minimum (18.0.0) or version string that cannot be parsed.
  • Runs offline. No API keys. No service to log into. Source files never leave the machine.

The same tool is the right primitive for both the human (npx ... | pbcopy) and the agent (scan → summarise → embed) without a separate code path.

Verify it yourself (5 lines)

# 1. Zero network calls
npx stapes-context-trim . >/dev/null && \
  lsof -p $$ -i 2>/dev/null | grep -E "node|npx" || \
  echo "no outgoing TCP from this shell"

# 2. No files written when --out is not set
npx stapes-context-trim . >/dev/null && \
  echo "no on-disk mutation"

# 3. Stable --json shape across runs
npx stapes-context-trim . --json | jq '{tool, version, fileCount}'

Worked example — feed a codebase to an LLM in one line

# Pipe straight into a chat prompt
npx stapes-context-trim . | pbcopy

# Same, but cap the digest at 200K chars and save to a file for review
npx stapes-context-trim . --max-total-chars 200000 --out context.md

# Get a structural summary before committing to paste the full digest
npx stapes-context-trim . --json | jq '.fileCount, .totalBytes, .skipped'

Compared to

| | stapes-context-trim | repomix | gitingest | code2prompt | |---|---|---|---|---| | Output formats | Markdown | XML, plain, Markdown | Markdown | Markdown | | Token counting | no | yes (tiktoken) | yes | no | | Compression | no | yes (configurable) | no | no | | .gitignore aware | yes | yes | yes | yes | | Symlink policy | off by default | configurable | n/a | n/a | | Runtime dependencies | 2 (commander, ignore) | 6+ | 4 | 3 | | Install | npx (no save) | npm i -g or local | uv tool install | go install | | Config to read for 80% of use | none | none | none | none | | Telemetry | none | none | none | none | | Output cap per file | configurable | configurable | configurable | configurable |

Use stapes-context-trim when you want one command, no install, no config. Use repomix when you need token counts or non-Markdown output. Use gitingest when the codebase is too large for a single digest and you need chunking.

Source

Visible at https://github.com/stapesco/context-trim. Built by stapes. Read the code. Fork it. Pull requests are not accepted.

See AGENTS.md for machine-readable install instructions and the stable --json schema.

Issues

GitHub issues are disabled on this repo. If the tool doesn't work for you, the fix is most likely in the three files under src/. Read them, fork, patch.

For security disclosures, see SECURITY.md.

License

MIT