Packaging & detection
What contextzip puts in a ZIP, what it leaves out, how it figures out your stack — and how to override any of it.
Stack detection
contextzip recognises a stack from its marker files — package.json, next.config.*, pyproject.toml, manage.py, Cargo.toml, go.mod, Gemfile — and applies that ecosystem's exclusion rules automatically.
It doesn't stop at the project root. A bounded scan looks two folder levels deep (configurable with scan_depth) and skips folders it never needs to enter, like node_modules/ and .venv/. So a monorepo with a Next.js frontend/ and a FastAPI backend/ gets both rule sets at once.
Pick the stacks in your repo — monorepos get all of them
Every project plus secrets — see below
Detected today: Next.js, Node.js, Django, FastAPI, Python, Rust, Go and Ruby. Packages a monorepo declares — npm, yarn or pnpm workspaces, lerna.json, Cargo workspaces, go.work — are checked whatever their depth. A project contextzip doesn't recognise still gets the universal rules below. Request your stack if it's missing.
What gets left out
On top of the stack rules, a universal set applies to every project:
| Category | Examples |
|---|---|
| Version control & editors | .git/ .svn/ .hg/ .vscode/ .idea/ *.swp |
| OS clutter | .DS_Store Thumbs.db desktop.ini |
| Logs, caches & temp | *.log logs/ .cache/ tmp/ *.tmp *.bak *.orig |
| Binaries & media | *.exe *.dll *.so *.png *.jpg *.svg *.mp4 *.zip *.tar *.gz |
| Project boilerplate | LICENSE CHANGELOG.md CONTRIBUTING.md SECURITY.md CODE_OF_CONDUCT.md |
| contextzip itself | .contextzip/ |
Secrets are left out, too
.env files, private keys, keystores, cloud and package-manager credentials, kubeconfigs and Terraform state are excluded on every run, including --git-changes. If you include one on purpose, its values are redacted. How secrets are handledYour .gitignore is honoured automatically, layered under contextzip's own rules. Use --no-gitignore to rely on the built-in rules alone.
Monorepos & subfolders
contextzip always works from the project root, wherever you run it — like git. Run cz inside frontend/ and it still packages the whole repo with root-relative paths, keeps one .contextzip/ at the root, and apply-zip puts files back in the right place.
~/projects/shop/frontend
$ cz --here
Working from the project root (..) · you're in frontend/ · packaging only frontend/ (--here)
✓ Detected FastAPI (backend/) + Next.js (frontend/) · high confidence
✓ Scanned 2,752 files & Packed 31 files · 131 KB → 44 KB, ↓66% smaller
The root is the outermost git repository above you — so the stray frontend/.git that create-next-app and create-vite leave behind doesn't hijack it — or, outside git, the folder that already has a .contextzip/. It never climbs above your home folder. --git-changes reads nested repos too, and CONTEXTZIP_ROOT pins the root when you need to.
No git at the top — just shop/frontend/.git and shop/backend/.git? contextzip asks once whether shop/ is the project root and remembers your answer. Inside a git submodule, it tells you it's working from the whole project, and --here packages just the submodule.
Paths you type are relative to where you are, like git add: from frontend/, cz include src/ means frontend/src/. Add --here to package only the folder you're in.
Include & exclude
contextzip include PATH… packages only the paths you name. contextzip exclude PATTERN… packages everything except what you name, in gitignore syntax. Both take the same flags as the main command, after the verb — like git or docker.
~/projects/my-app
$ contextzip include src/ .env --dry-run
✓ Detected Next.js + Node.js · high confidence
✓ Scanned 2,752 files · 32 included (131 KB), 2,720 excluded
! 1 normally excluded file included because you named it — 1 secret file, values will be redacted
Dry run — no ZIP created. Remove --dry-run to produce the archive.
Naming an excluded path brings it back. If a path you name is itself excluded — by a built-in rule, your .gitignore or always_exclude — it's included anyway, because you asked for it explicitly. Two guard rails keep that predictable:
- Excluded folders nested inside a named folder are still skipped:
include dist/leaves outdist/node_modules/. - Naming an ordinary folder only narrows the run:
include src/doesn't pull insrc/.env.
Paths match at folder boundaries (src matches src/index.ts, not src2/), and a leading ./ or .\ is ignored. For settings that apply on every run, use always_include and always_exclude.
Only what changed
--git-changes packages only the files git reports as staged, modified or untracked — ideal for reviews and “here's what I changed, what's wrong?” prompts. The project must be inside a git repository; it works from any subfolder of a monorepo.
~/projects/my-app
$ contextzip --git-changes
✓ Detected Next.js + Node.js · high confidence
✓ Found 9 changed files & Packed 9 files · 2 staged, 4 unstaged, 3 untracked, 118 KB → 39 KB
✓ Saved to · .contextzip/output/git-changes/changes.zip
✓ Ready to paste
Deleted files and submodules are reported rather than silently dropped, and the secret rules still apply to files git tracks — a committed .env stays out. include and exclude work here too.
Warnings & the report
Large files (1 MB or more by default, set with limits.max_file_size_mb) and binary files are flagged before you spend an upload on something an AI can't read. Dangling symlinks, unreadable files and anything pointing outside the project are skipped and reported, never silently dropped.
Every run writes a plain-text report next to the ZIP — codebase.report.txt beside codebase.zip — listing what was included, what was excluded and why, what was redacted, and anything left out of the archive.
~/projects/my-app
$ contextzip
✓ Scanned 2,752 files & Packed 46 files · 212 KB → 71 KB, ↓66% smaller
! 1 large file (≥ 1.0 MB) will be included
! 1 binary file detected — AI tools may not read them
Full report: .contextzip/output/codebase/codebase.report.txt