docs: update README for clarity and improved feature descriptions

This commit is contained in:
akadeepesh
2026-05-24 01:56:55 +05:30
parent 30568d15a1
commit 5f99b04046
+64 -323
View File
@@ -1,37 +1,31 @@
# contextzip
> Stop copy-pasting files manually. Package exactly the right parts of your codebase and paste it straight into Claude, ChatGPT, or any AI tool in one command.
> Package exactly the right parts of your codebase and paste it into any AI tool — in one command.
```
contextzip
```bash
pip install contextzip
```
---
## The problem
## Why contextzip
Every time you want help from an AI tool, you go through the same ritual:
Every AI session starts the same way: hunt down the relevant files, manually skip `node_modules`, build artifacts, and lock files, zip them, find the zip, upload it. Then do it all again next session.
1. Find the relevant files in your project
2. Skip `node_modules`, `.next`, `__pycache__`, build artifacts, lock files...
3. Select the right ones, zip them, find the zip, upload it
4. Repeat every single session
contextzip eliminates that entirely. Run it from your project root, it detects your stack, applies smart exclusions, produces a lean ZIP, and opens your file manager with the archive already selected. One `Ctrl+C` and you're done.
contextzip eliminates that entirely. Run it from your project root — it detects your stack, applies smart exclusions, produces a lean ZIP, and opens your file manager with the archive already selected. One `Ctrl+C` and you're done.
---
## Features
- **Smart framework detection** : automatically identifies Node.js, Next.js, Python, Django, FastAPI, Rust, Go, Ruby and applies the right exclusion rules for each
- **Respects your `.gitignore`** : patterns from your existing gitignore are honoured automatically
- **Git-aware packaging** : package only modified, staged, unstaged, and untracked files with `--git-changes` — perfect for AI review sessions, incremental debugging, and PR workflows
- **AI-powered file selection** : describe your task in plain English with `--prompt` and Gemini selects the minimum relevant files automatically — no manual hunting required
- **Persistent workspace** : all generated ZIPs land in a `.contextzip/` directory at your project root, not a random temp folder — discoverable, reusable, and git-ignored automatically
- **Warns before it's a problem** : flags large files (≥ 1 MB) and binary files that AI tools can't read, before you waste an upload
- **Handles the messy stuff** : dangling symlinks, unreadable files, and files outside the project tree are all caught and reported, never silently dropped
- **Full CLI control** : `--include`, `--exclude`, `--dry-run`, `--verbose`, `--output`, all composable
- **Cross-platform clipboard integration** : copies the file to clipboard on macOS/Linux; opens Explorer with the ZIP selected on Windows
- **Smart framework detection** — automatically identifies Node.js, Next.js, Python, Django, FastAPI, Rust, Go, and Ruby, applying the right exclusion rules for each
- **Respects `.gitignore`** — your existing ignore patterns are honoured automatically
- **Git-aware packaging** — use `--git-changes` to package only modified, staged, and untracked files; perfect for incremental debugging and PR review sessions
- **AI-powered file selection** — describe your task in plain English with `--prompt` and Gemini selects the minimum relevant files automatically, no manual hunting required
- **Persistent workspace** — all generated ZIPs land in `.contextzip/` at your project root, discoverable, reusable, and git-ignored automatically
- **Warns before it's a problem** — flags large (≥ 1 MB) and binary files that AI tools can't read, before you waste an upload
- **Handles edge cases** — dangling symlinks, unreadable files, and paths outside the project tree are caught and reported, never silently dropped
- **Full CLI control** — `--include`, `--exclude`, `--dry-run`, `--output`, all composable
---
@@ -43,13 +37,13 @@ contextzip eliminates that entirely. Run it from your project root, it detects y
pip install contextzip
```
Or with [pipx](https://pipx.pypa.io/) (recommended for CLI tools, keeps it isolated):
With [pipx](https://pipx.pypa.io/) (recommended for CLI tools — keeps it isolated):
```bash
pipx install contextzip
```
Verify the install:
Verify:
```bash
contextzip --version
@@ -66,13 +60,12 @@ cd ~/projects/my-app
contextzip
```
That's it. contextzip will:
contextzip will:
1. Detect your framework (e.g. `Next.js + Node.js`)
2. Apply the appropriate exclusion rules
3. Scan and summarise what will be included
4. Create a compressed ZIP in `.contextzip/` at your project root
5. Open your file manager with the ZIP selected and ready to copy
3. Create a compressed ZIP in `.contextzip/` at your project root
4. Open your file manager with the ZIP selected and ready to copy
---
@@ -84,352 +77,100 @@ contextzip [OPTIONS]
| Option | Description |
|---|---|
| `-p`, `--prompt TEXT` | Describe your task in plain English. Gemini AI selects only the relevant files. Requires a free API key (guided setup on first use). |
| `-i`, `--include PATH` | Only include files under this path. Repeatable. |
| `-e`, `--exclude PATTERN` | Extra exclusion patterns (gitignore syntax). Repeatable. |
| `exclude` | Subcommand: exclude specific files/patterns. `contextzip exclude CHANGELOG.md LICENSE .github/` |
| `include` | Subcommand: include only specific paths. `contextzip include src/ app/` |
| `config` | Subcommand: manage configuration (API key). `contextzip config --reset-key` |
| `--git-changes` | Only include files reported by git as modified, staged, or untracked. |
| `-n`, `--dry-run` | Preview what would be included, no ZIP created. |
| `-o`, `--output FILE` | Write ZIP to a custom path. Bypasses the `.contextzip/` workspace entirely. |
| `--no-clipboard` | Skip the clipboard / folder-open step. |
| `--no-gitignore` | Ignore the project's `.gitignore` file. |
| `-v`, `--verbose` | Show every included and excluded file with sizes. |
| `-h`, `--help` | Show help and exit. |
| `--version` | Show version and exit. |
| `-p`, `--prompt TEXT` | Describe your task in plain English — Gemini selects only the relevant files |
| `-i`, `--include PATH` | Only include files under this path (repeatable) |
| `-e`, `--exclude PATTERN` | Add exclusion patterns in gitignore syntax (repeatable) |
| `--git-changes` | Only include files reported by git as modified, staged, or untracked |
| `-n`, `--dry-run` | Preview what would be included without creating a ZIP |
| `-o`, `--output FILE` | Write ZIP to a custom path |
| `-v`, `--verbose` | Show every included and excluded file with sizes |
| `--no-clipboard` | Skip the clipboard / folder-open step |
| `--no-gitignore` | Ignore the project's `.gitignore` |
**Subcommands:** `exclude`, `include`, `config` — run `contextzip --help` for full details.
---
## Examples
**Preview what would be packaged (no ZIP created):**
```bash
contextzip --dry-run
```
**Only package specific directories:**
```bash
contextzip --include src --include app
```
**Exclude additional patterns beyond the auto-rules:**
```bash
contextzip --exclude "*.log" --exclude "*.sqlite" --exclude "tests/"
```
**Exclude files using the subcommand (space-separated, no repetition):**
```bash
contextzip exclude CHANGELOG.md CONTRIBUTING.md LICENSE .github/
```
**Exclude with flags:**
```bash
contextzip exclude CHANGELOG.md --dry-run --verbose
```
**Include only specific directories using the subcommand:**
```bash
contextzip include src/ app/
```
**Only package files changed in git:**
```bash
contextzip --git-changes
```
**Save ZIP to a specific path (bypasses workspace):**
```bash
contextzip --output ~/Desktop/my-project-context.zip
```
**Full verbose audit, see every file decision:**
```bash
# Preview what would be packaged
contextzip --dry-run --verbose
```
**Combine include + extra excludes:**
```bash
contextzip --include src --exclude "**/*.test.ts"
```
# Package only specific directories
contextzip --include src --include app
**Let AI select only the files relevant to your task:**
```bash
# Exclude additional patterns
contextzip --exclude "*.log" --exclude "tests/"
# Package only git-modified files
contextzip --git-changes
# Let AI pick only the files relevant to your task
contextzip --prompt "Change toast color on failed login"
```
**Preview AI file selection without creating a ZIP:**
```bash
# Preview AI file selection without creating a ZIP
contextzip --prompt "Refactor auth middleware" --dry-run
# Save to a custom path
contextzip --output ~/Desktop/project-context.zip
```
---
## AI-powered file selection
The `--prompt` flag lets you describe a task in plain English. contextzip scans your project, builds a lightweight file map, and asks Gemini to select the minimum set of files needed for that task. The result is a tightly scoped ZIP — only what you'd actually open to make the change.
The `--prompt` flag lets you describe a task in plain English. contextzip scans your project, builds a lightweight file map, and asks Gemini to return the minimum set of files needed for that task — typically 2–5, never more than 10. The result is a tightly scoped ZIP with only what you'd actually open to make the change.
```bash
contextzip --prompt "Change toast color on failed login"
# → components/ui/toast.tsx, app/login/page.tsx, lib/auth.ts
```
Example selected files:
```
components/ui/toast.tsx
app/login/page.tsx
lib/auth.ts
```
The ZIP also includes a `prompt.txt` describing the task, so when you drop it into Claude, ChatGPT, or any other AI tool, it immediately understands what you're trying to do.
The ZIP also includes a `prompt.txt` that describes the task and lists the selected files. When you drop the ZIP into Claude, ChatGPT, or any other AI tool, it immediately knows what you're trying to do.
### First-time setup
`--prompt` requires a free Gemini API key from [Google AI Studio](https://aistudio.google.com/apikey) — no credit card needed. On first use, contextzip will guide you through getting and saving one:
```
╭─ Gemini API Key Required ──────────────────────────────────╮
│ │
│ --prompt requires a free Gemini API key. │
│ contextzip uses Google AI Studio — no credit card needed. │
│ │
│ Get your free key at: │
│ https://aistudio.google.com/apikey │
│ │
╰─────────────────────────────────────────────────────────────╯
Open Google AI Studio in your browser now? [Y/n]:
```
Your key is saved to `~/.config/contextzip/config.json` (Linux/macOS) or `%APPDATA%\contextzip\config.json` (Windows) and reused automatically on every subsequent run.
You can also set the key as an environment variable to skip the config file entirely:
**First-time setup:** `--prompt` requires a free Gemini API key from [Google AI Studio](https://aistudio.google.com/apikey) — no credit card needed. On first use, contextzip guides you through obtaining and saving one. You can also skip the setup entirely with an environment variable:
```bash
export GEMINI_API_KEY=AIza...
```
### Managing your API key
Manage your key at any time:
```bash
contextzip config # show current key status
contextzip config --reset-key # clear stored key and re-run setup
contextzip config --show-key-path # print the config file location
contextzip config # show current key status
contextzip config --reset-key # clear and re-run setup
```
### How file selection works
1. contextzip scans the project and applies all standard exclusions (no `node_modules`, no build artifacts, no `.env` files)
2. A lightweight file map (relative paths + file sizes) is sent to Gemini along with your task description and detected framework
3. Gemini returns a ranked list of the most relevant files — typically 2–5, never more than 10
4. Only those files are packaged, plus a `prompt.txt` describing the task
The goal is minimum viable context. Sending fewer, more relevant files gets better AI responses and wastes fewer tokens.
---
## Workspace directory
## What gets excluded
contextzip stores all generated packages in a `.contextzip/` directory at your project root, keeping your AI context artifacts persistent, discoverable, and out of the way.
contextzip stacks exclusion rules based on your detected stack, on top of your `.gitignore`.
### Location
**Always excluded:** `.git/`, `.env` files, logs, caches, editor config (`.vscode/`, `.idea/`), OS files (`.DS_Store`, `Thumbs.db`), and common binary formats.
contextzip looks for a `.git/` directory walking up from your current working directory and places `.contextzip/` alongside it — the true project root. If no git repository is found, it falls back to the current working directory.
**By framework:**
### Output naming
The output filename is determined by how you invoke contextzip:
| Command | Output |
| Stack | Additional exclusions |
|---|---|
| `contextzip` | `.contextzip/codebase.zip` |
| `contextzip --git-changes` | `.contextzip/changes.zip` |
| `contextzip --prompt "..."` | `.contextzip/codebase.zip` (AI-scoped) |
| `contextzip --output PATH` | `PATH` (workspace bypassed entirely) |
| Node.js / Next.js | `node_modules/`, `.next/`, `dist/`, `build/`, lock files, `*.min.js`, `*.d.ts` |
| Python / Django / FastAPI | `__pycache__/`, `.venv/`, `*.pyc`, `migrations/`, `.pytest_cache/`, lock files |
| Rust | `target/`, `Cargo.lock`, `*.rlib` |
| Go | `vendor/`, `go.sum`, `bin/` |
All other flags (`--include`, `--exclude`, subcommands) do not affect the filename — they refine what goes into `codebase.zip`.
Each run overwrites the previous file of the same name, so `.contextzip/codebase.zip` is always your latest snapshot.
### `.gitignore` management
contextzip automatically keeps `.contextzip/` out of version control:
- If `.gitignore` exists → `.contextzip/` is appended if not already present
- If `.gitignore` does not exist and a `.git/` directory is found → a minimal `.gitignore` is created containing `.contextzip/`
- If no git repository is detected → `.gitignore` is left untouched
The `.contextzip/` directory is also always excluded from packaging itself, regardless of `.gitignore` state.
### Workspace structure
```
project/
├── .contextzip/
│ ├── codebase.zip ← latest full snapshot
│ └── changes.zip ← latest git-changes snapshot
├── src/
└── ...
```
---
## Framework detection & auto-exclusions
contextzip detects your stack from config files in the project root and stacks the appropriate rules.
### Detection signals
| File found | Detected as |
|---|---|
| `next.config.js` / `.ts` / `.mjs` or `"next"` in `package.json` | Next.js |
| `package.json` | Node.js |
| `manage.py` or `"django"` in requirements | Django |
| `"fastapi"` in requirements | FastAPI |
| `requirements.txt` / `pyproject.toml` / `setup.py` | Python |
| `Cargo.toml` | Rust |
| `go.mod` | Go |
| `Gemfile` | Ruby |
Detection is **additive**. A monorepo with both `package.json` and `pyproject.toml` will have both rule sets applied.
### What gets excluded
**Always (every project):**
`.git/`, `.env`, `.env.*`, `*.log`, `logs/`, `.cache/`, `tmp/`, `.contextzip/`, editor files (`.vscode/`, `.idea/`), OS files (`.DS_Store`, `Thumbs.db`), common binary formats (images, audio, video, archives)
**Node.js / Next.js:**
`node_modules/`, `.next/`, `.nuxt/`, `dist/`, `build/`, `out/`, `.turbo/`, `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`, `*.min.js`, `*.d.ts`, `tsconfig.tsbuildinfo`
**Python:**
`__pycache__/`, `*.pyc`, `.venv/`, `venv/`, `*.egg-info/`, `.pytest_cache/`, `.mypy_cache/`, `.ruff_cache/`, `htmlcov/`, `*.sqlite3`, `migrations/`, `poetry.lock`, `uv.lock`
**Rust:**
`target/`, `Cargo.lock`, `*.rlib`, `*.rmeta`
**Go:**
`vendor/`, `go.sum`, `bin/`
Plus any patterns from your project's own `.gitignore`.
---
## Clipboard behaviour
contextzip uses a tiered strategy so it never just fails silently:
| Platform | Tier 1 (auto) | Tier 2 (fallback) | Tier 3 (last resort) |
|---|---|---|---|
| **macOS** | File copied to clipboard via Finder, paste directly into browser | `open -R` reveals ZIP in Finder | Path printed to terminal |
| **Linux** | `xclip` copies file bytes with `application/zip` MIME type | `xdg-open` opens containing folder | Path printed to terminal |
| **Windows** | - | `explorer /select,"..."` opens Explorer with ZIP highlighted → `Ctrl+C` | Path printed to terminal |
On **macOS** and **Linux with xclip**, you can paste the ZIP directly into an upload zone (Claude, ChatGPT, etc.), no file picker needed. On **Windows**, Explorer opens with the file already selected so one `Ctrl+C` is all it takes.
---
## Warnings
contextzip surfaces issues before they waste your time:
**Large files (≥ 1 MB)** : listed with sizes and a suggestion to exclude if unneeded. AI context windows have limits; a 5 MB log file helps no one.
**Binary files** : files detected as binary (null bytes in the first 512 bytes) are flagged. Most AI tools can't read binary content; you may want to exclude them.
**Skipped files** : dangling symlinks, permission-denied files, and paths outside the project tree are listed with their specific reason rather than silently dropped.
---
## Project structure
```
contextzip/
├── contextzip/
│ ├── __init__.py # version string
│ ├── cli.py # Click entry point, all flags, subcommands (exclude, include, config), rich output
│ ├── config.py # API key storage (~/.config/contextzip/config.json)
│ ├── detector.py # framework/language detection engine
│ ├── filters.py # pathspec-based file filtering + ResolveResult
│ ├── git.py # git status parsing + changed-file detection
│ ├── packager.py # ZIP creation, workspace management, PackageResult
│ ├── clipboard.py # tiered clipboard strategy (all platforms)
│ ├── ai/
│ │ ├── __init__.py
│ │ ├── gemini.py # Gemini API client (file relevance selection)
│ │ └── selector.py # project map builder + AI orchestration + prompt.txt
│ └── rules/
│ ├── base.py # universal exclusions (includes .contextzip/)
│ ├── node.py # Node.js / Next.js / Vite
│ ├── python.py # Python / Django / FastAPI
│ ├── rust.py # Rust / Cargo
│ └── go.py # Go modules
└── pyproject.toml
```
---
## Adding a new language / framework
1. Create `contextzip/rules/yourlang.py` with a `PATTERNS` list using gitignore syntax:
```python
PATTERNS = [
"build/",
"*.compiled",
".cache/",
]
```
2. Register it in `filters.py`:
```python
_RULE_REGISTRY: dict[str, str] = {
...
"yourlang": "contextzip.rules.yourlang",
}
```
3. Add a detection rule in `detector.py`:
```python
_Rule(
name="YourLang",
module="yourlang",
check=lambda p: _file_exists(p, "yourlang.config"),
weight=3,
),
```
That's it. Detection, filtering, and CLI output all pick it up automatically.
---
## Dependencies
| Package | Purpose |
|---|---|
| [`click`](https://click.palletsprojects.com/) | CLI framework |
| [`rich`](https://rich.readthedocs.io/) | Terminal output, panels, progress bars |
| [`pathspec`](https://github.com/cpburnz/python-pathspec) | Gitignore-style pattern matching |
| [`httpx`](https://www.python-httpx.org/) | HTTP client for Gemini API calls (required for `--prompt`) |
`httpx` is only used when `--prompt` is invoked. All other contextzip features work without it, but it must be installed for AI-powered file selection.
Detection is additive — a monorepo with both `package.json` and `pyproject.toml` gets both rule sets applied.
---
## Contributing
Contributions are welcome, especially new framework rule sets, edge case fixes, and platform-specific clipboard improvements.
Contributions are welcome — especially new framework rule sets, edge case fixes, and platform-specific clipboard improvements.
```bash
git clone https://github.com/akadeepesh/contextzip
cd contextzip
pip install -e .
```
Please open an issue before submitting a large PR so we can discuss the approach first.
See [CONTRIBUTING.md](https://github.com/akadeepesh/contextzip/blob/main/CONTRIBUTING.md) for local setup, how to add a new framework, and PR guidelines. Please open an issue before starting a large PR so we can align on the approach first.
---
## License
MIT - see [LICENSE](https://github.com/akadeepesh/smart-context-packager/blob/main/LICENSE) for details.
MIT — see [LICENSE](https://github.com/akadeepesh/contextzip/blob/main/LICENSE) for details.