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:
> 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.