ctxbundle
Bundle a code repository into a single LLM-ready text file.
ctxbundle walks a directory, drops binaries / lockfiles / build output, respects .gitignore, prioritizes the files an LLM actually wants to see, and emits a single text artifact you can paste into any chat window.
Zero API calls. Zero ML dependencies. Just click and pathspec.
Why this exists
Pasting a whole repo into a chat is annoying. Existing tools either:
- Dump every file (including
node_modulesand PNGs) and blow your context window - Need an API key or a model to summarize
- Make you hand-curate the file list every time
ctxbundle does the boring middle layer: pick the right files, keep them inside a token budget, format the result so an LLM can navigate it on a single read. It runs offline, finishes in seconds, and produces deterministic output you can diff.
Install
pip install ctxbundle
Or from source:
git clone https://github.com/pranavviswanathan/ctxbundle
cd ctxbundle
pip install -e .
Requires Python 3.8+.
Usage
ctxbundle . # pack current directory to stdout
ctxbundle ./myrepo # pack a specific path
ctxbundle . --limit 100k # token limit (default 200k)
ctxbundle . --out context.txt # write to file instead of stdout
ctxbundle . --ignore tests/ docs/ # additional ignore patterns
ctxbundle . --summarize # summarize large files instead of truncating
--limit accepts integers, k (thousands), or m (millions): 50000, 100k, 1.5m.
--ignore is repeatable and accepts gitignore-style globs:
ctxbundle . --ignore "*.test.ts" --ignore "fixtures/"
What gets included
ctxbundle always skips:
- VCS / build / cache directories:
.git,node_modules,__pycache__,build/,dist/,.venv,target,.next, ... - Lockfiles:
package-lock.json,yarn.lock,poetry.lock,Cargo.lock,*.lock - Binaries and media:
*.png,*.jpg,*.pdf,*.zip,*.so,*.dll, fonts, audio, video - Generated noise:
*.log,*.pyc,*.min.js,*.map - Secrets:
.env,.env.*
On top of that, it honors your .gitignore and any --ignore patterns you pass.
How budget allocation works
When the repo fits inside --limit, every text file is included verbatim.
When it doesn't, files are ranked and packed in priority order:
- Entry points (
main.py,index.js,app.py,server.js,main.go, ...) - README files
- Source code (
.py,.ts,.go,.rs,.java, ...) - Configs (
pyproject.toml,package.json,Dockerfile, ...) - Tests
- Everything else
A single file is capped at roughly 10% of the total budget. Files exceeding that cap are either truncated (with a [FILE TRUNCATED - N lines omitted] marker) or, with --summarize, replaced by a heuristic summary: first 20 lines, last 10 lines, plus a list of function/class names found via regex.
Output format
=== CONTEXTPACK ===
Repo: myrepo
Files included: 23 of 31
Estimated tokens: 94,200 / 200,000
Skipped (too large): migrations.sql, package-lock.json
Generated: 2025-01-15 14:32
=== FILE: src/main.py ===
[file contents]
=== FILE: src/utils/helpers.py ===
[file contents]
...
The === FILE: <path> === delimiter is unambiguous and easy for an LLM to parse on a single pass.
Token estimation
Token counts use a chars / 4 heuristic. It matches BPE tokenizers within ~10% on typical source code — close enough for budgeting, and free of ML dependencies.
Library use
from pathlib import Path
from ctxbundle.walker import walk
from ctxbundle.tokenizer import rank, estimate_tokens
entries = walk(Path("./myrepo"), extra_ignores=["docs/"])
ranked = rank(entries)
for rf in ranked[:10]:
print(rf.priority, rf.tokens, rf.entry.path)
Publishing (maintainers)
pip install --upgrade build twine
python -m build
python -m twine upload dist/*
License
MIT.
Metadata
Release files for ctxbundle 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ctxbundle-0.1.2.tar.gz | 11.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ctxbundle-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 23.4 kB
Release files / ctxbundle-0.1.2.tar.gz
| Download URL | ctxbundle-0.1.2.tar.gz |
|---|---|
| Size | 11.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
de698961082012b3e5d0d7d2f159418e56fa6134e9625bcd3d7291eef863c056
|
|
BLAKE2b-256 checksum How to use checksums |
980eaf0c82aba99902077241c122c450640f2b51614461f3c5737e34dd6bede5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.2
|
Release files / ctxbundle-0.1.2-py3-none-any.whl
| Download URL | ctxbundle-0.1.2-py3-none-any.whl |
|---|---|
| Size | 11.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0ff6253d148d2ba4dc70c0770379df95b663599efeb695c58f11d969c4ddd1a7
|
|
BLAKE2b-256 checksum How to use checksums |
ba4d404b0c07dffcef7f598ce5379484b1d3ddb17c021aae190e9f8249ec337f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.2
|