# I built ctxstash: pack a codebase into one LLM-ready file, with a token count

> Source: <https://dev.to/_06a3df6b50aec966668fb/i-built-ctxstash-pack-a-codebase-into-one-llm-ready-file-with-a-token-count-4n7l>
> Published: 2026-06-13 16:45:52+00:00

You're debugging something with ChatGPT, Claude, or Cursor, and you hit the wall every developer knows: the model needs to *see* your code. So you start the dance — open a file, copy, paste, type "and here's the other file", paste again, label it so the model doesn't get confused… five files later you paste the whole thing and get back **"this conversation is too long."** Now you're trimming blind, with no idea how many tokens you actually sent.

I got tired of doing this by hand, so I built **ctxstash**: one command that walks a directory and emits a single, tidy Markdown document with every file fenced and language-tagged, a file-tree overview at the top, and an approximate token count so you know up front whether it'll fit.

```
npx ctxstash src > context.md
✓ packed 23 files · 142.3 KB · ~38,210 tokens
```

Paste `context.md`

into the model. Done.

There's a great Python tool, `files-to-prompt`

, that inspired this — but it's Python-only and doesn't estimate tokens. I wanted something with **zero dependencies**, a **token estimate built in**, and an **identical build on both npm and PyPI** so it doesn't matter which ecosystem you live in.

```
ctxstash .                      # pack the current dir to stdout
ctxstash src tests -o ctx.md    # pack two dirs, write to a file
ctxstash . -i "*.ts,*.tsx"      # only TypeScript
ctxstash . -e "*.test.js"       # drop tests
ctxstash . --estimate           # just tell me the token cost, pack nothing
ctxstash src --tree             # just the file tree
```

`--estimate`

is the one I reach for most — it answers "will this fit in the context window?" without producing a wall of text:

```
files    23
size     142.3 KB
~tokens  38,210 (estimate, ~4 chars/token)

largest by tokens
     ~6,210  src/bundle.ts
     ~3,180  src/core.ts
     ...
```

The packed output looks like this:

```
# Repository context

> Packed by ctxstash — 3 files, 4.1 KB, ~1,040 tokens (estimate).

## File tree

src/
  core.ts
  cli.ts
README.md

## Files

### src/core.ts
...fenced, language-tagged contents...
```

By default it **skips the junk automatically** — `node_modules`

, `.git`

, `dist`

, lockfiles, minified bundles, and binary files (images, fonts, compiled artifacts) never end up in your context. The summary always goes to **stderr**, so `ctxstash > context.md`

keeps the file clean while you still see the count.

```
npx ctxstash .          # Node ≥ 18, nothing to install
pip install ctxstash    # Python ≥ 3.8
```

Both builds are **zero-dependency** and behavior-identical.

`````

run (hello, every Markdown file), ctxstash wraps it in a `.txt`

name still gets skipped.`npx`

/`pip install`

and go.

```
npx ctxstash . --estimate
```

It's MIT-licensed and open source:

How are you feeding code to LLMs right now — manual copy-paste, a custom script, or something else? And what would make a tool like this actually fit your workflow? I'd genuinely like to know what to build next.
