Bundle a code repository into a single LLM-ready text file.
Project description
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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ctxbundle-0.1.2.tar.gz.
File metadata
- Download URL: ctxbundle-0.1.2.tar.gz
- Upload date:
- Size: 11.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
de698961082012b3e5d0d7d2f159418e56fa6134e9625bcd3d7291eef863c056
|
|
| MD5 |
c94df29ab48d9f163ea21f3202608e4e
|
|
| BLAKE2b-256 |
980eaf0c82aba99902077241c122c450640f2b51614461f3c5737e34dd6bede5
|
File details
Details for the file ctxbundle-0.1.2-py3-none-any.whl.
File metadata
- Download URL: ctxbundle-0.1.2-py3-none-any.whl
- Upload date:
- Size: 11.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0ff6253d148d2ba4dc70c0770379df95b663599efeb695c58f11d969c4ddd1a7
|
|
| MD5 |
871a4e5e649d0231300aff197ce1d295
|
|
| BLAKE2b-256 |
ba4d404b0c07dffcef7f598ce5379484b1d3ddb17c021aae190e9f8249ec337f
|