contextzip 0.4.5__tar.gz → 0.4.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. contextzip-0.4.7/PKG-INFO +408 -0
  2. contextzip-0.4.7/README.md +379 -0
  3. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/__init__.py +1 -1
  4. contextzip-0.4.7/contextzip/_x11_clip.py +338 -0
  5. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/cli.py +1 -0
  6. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/cli_display.py +31 -4
  7. contextzip-0.4.7/contextzip/clipboard.py +552 -0
  8. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/filters.py +72 -11
  9. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/packager.py +31 -2
  10. contextzip-0.4.7/contextzip/redact.py +337 -0
  11. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/report.py +25 -2
  12. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/rules/base.py +37 -27
  13. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/watcher.py +8 -2
  14. contextzip-0.4.7/contextzip.egg-info/PKG-INFO +408 -0
  15. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip.egg-info/SOURCES.txt +1 -0
  16. {contextzip-0.4.5 → contextzip-0.4.7}/pyproject.toml +1 -1
  17. contextzip-0.4.5/PKG-INFO +0 -104
  18. contextzip-0.4.5/README.md +0 -75
  19. contextzip-0.4.5/contextzip/clipboard.py +0 -223
  20. contextzip-0.4.5/contextzip/redact.py +0 -175
  21. contextzip-0.4.5/contextzip.egg-info/PKG-INFO +0 -104
  22. {contextzip-0.4.5 → contextzip-0.4.7}/LICENSE +0 -0
  23. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/ai/__init__.py +0 -0
  24. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/ai/gemini.py +0 -0
  25. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/ai/heuristic.py +0 -0
  26. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/ai/selector.py +0 -0
  27. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/api.py +0 -0
  28. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/applier.py +0 -0
  29. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/cleanup.py +0 -0
  30. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/cli_ai.py +0 -0
  31. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/cli_onboard.py +0 -0
  32. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/config.py +0 -0
  33. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/detector.py +0 -0
  34. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/error_parser.py +0 -0
  35. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/git.py +0 -0
  36. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/project_config.py +0 -0
  37. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/rules/__init__.py +0 -0
  38. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/rules/errors/__init__.py +0 -0
  39. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/rules/errors/node.py +0 -0
  40. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/rules/errors/python.py +0 -0
  41. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/rules/go.py +0 -0
  42. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/rules/node.py +0 -0
  43. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/rules/python.py +0 -0
  44. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/rules/ruby.py +0 -0
  45. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/rules/rust.py +0 -0
  46. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/updater.py +0 -0
  47. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/webui/__init__.py +0 -0
  48. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/webui/assets.py +0 -0
  49. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/webui/persist.py +0 -0
  50. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/webui/server.py +0 -0
  51. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip/webui/suggestions.py +0 -0
  52. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip.egg-info/dependency_links.txt +0 -0
  53. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip.egg-info/entry_points.txt +0 -0
  54. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip.egg-info/requires.txt +0 -0
  55. {contextzip-0.4.5 → contextzip-0.4.7}/contextzip.egg-info/top_level.txt +0 -0
  56. {contextzip-0.4.5 → contextzip-0.4.7}/setup.cfg +0 -0
@@ -0,0 +1,408 @@
1
+ Metadata-Version: 2.4
2
+ Name: contextzip
3
+ Version: 0.4.7
4
+ Summary: Intelligently package your codebase for AI tools
5
+ Author-email: Deepesh <akadeepesh@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/akadeepesh/contextzip
8
+ Project-URL: Repository, https://github.com/akadeepesh/contextzip
9
+ Project-URL: Issues, https://github.com/akadeepesh/contextzip/issues
10
+ Keywords: ai,cli,developer-tools,context,zip,llm,claude,chatgpt,code-packaging
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Software Development :: Build Tools
20
+ Classifier: Topic :: Utilities
21
+ Requires-Python: >=3.9
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: click>=8.1
25
+ Requires-Dist: rich>=13.0
26
+ Requires-Dist: pathspec>=0.12
27
+ Requires-Dist: httpx>=0.27
28
+ Dynamic: license-file
29
+
30
+ <div align="center">
31
+
32
+ # contextzip
33
+
34
+ **Package exactly the right parts of your codebase for any AI tool, in one command.**
35
+
36
+ [![PyPI](https://img.shields.io/pypi/v/contextzip?color=blue)](https://pypi.org/project/contextzip/)
37
+ [![Python](https://img.shields.io/pypi/pyversions/contextzip)](https://pypi.org/project/contextzip/)
38
+ [![Downloads](https://static.pepy.tech/badge/contextzip/month)](https://pepy.tech/project/contextzip)
39
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/akadeepesh/contextzip/blob/main/LICENSE)
40
+
41
+ [Documentation](https://contextzip.vercel.app) ·
42
+ [CLI reference](https://github.com/akadeepesh/contextzip/blob/main/CLI.md) ·
43
+ [Changelog](https://github.com/akadeepesh/contextzip/blob/main/CHANGELOG.md) ·
44
+ [Report a bug](https://github.com/akadeepesh/contextzip/issues/new/choose)
45
+
46
+ </div>
47
+
48
+ https://github.com/user-attachments/assets/91913ad6-6161-430d-9075-b0fa76498021
49
+
50
+ ---
51
+
52
+ ## Why contextzip?
53
+
54
+ Every AI coding session starts the same way. You hunt down the relevant files, skip `node_modules` and build output by hand, zip it all, find the zip and upload it. Next session, you do it again.
55
+
56
+ contextzip does all of that for you. Run it from your project root and it:
57
+
58
+ 1. **Detects your stack** (Node.js, Next.js, Python, Django, FastAPI, Rust, Go, Ruby, monorepos included).
59
+ 2. **Excludes the noise**: dependencies, build output, caches, binaries, logs, and anything in your `.gitignore`.
60
+ 3. **Keeps secrets out**: `.env` files, private keys, cloud credentials and Terraform state are left out by default. If you include your `.env` on purpose, its values are redacted.
61
+ 4. **Puts the ZIP on your clipboard** as a real file, so you can paste it straight into Claude, ChatGPT, Gemini or any other upload box.
62
+
63
+ When the AI sends changed files back, `contextzip apply-zip` writes them into your project safely, and warns you before touching anything you've edited since.
64
+
65
+ ## Table of contents
66
+
67
+ - [Installation](#installation)
68
+ - [Quick start](#quick-start)
69
+ - [Features](#features)
70
+ - [Smart packaging](#smart-packaging)
71
+ - [Package only what changed](#package-only-what-changed)
72
+ - [AI-powered file selection](#ai-powered-file-selection)
73
+ - [Applying AI changes back](#applying-ai-changes-back)
74
+ - [Terminal error watcher](#terminal-error-watcher)
75
+ - [Visual config UI](#visual-config-ui)
76
+ - [Command reference](#command-reference)
77
+ - [Configuration](#configuration)
78
+ - [What is always excluded](#what-is-always-excluded)
79
+ - [Where files go](#where-files-go)
80
+ - [Python API](#python-api)
81
+ - [Privacy & security](#privacy--security)
82
+ - [Platform support](#platform-support)
83
+ - [Contributing](#contributing)
84
+ - [License](#license)
85
+
86
+ ## Installation
87
+
88
+ contextzip needs **Python 3.9 or newer**.
89
+
90
+ ```bash
91
+ pip install contextzip
92
+ ```
93
+
94
+ Installing with [pipx](https://pipx.pypa.io/) or [uv](https://docs.astral.sh/uv/) keeps it isolated from your projects:
95
+
96
+ ```bash
97
+ pipx install contextzip
98
+ # or
99
+ uv tool install contextzip
100
+ ```
101
+
102
+ This installs two commands that do the same thing: `contextzip` and the shorter `cz`.
103
+
104
+ To update later, run `contextzip update`. It works out whether you installed with pip, pipx or uv and upgrades the right one.
105
+
106
+ ## Quick start
107
+
108
+ ```bash
109
+ cd ~/projects/my-app
110
+ contextzip
111
+ ```
112
+
113
+ You don't need any flags. contextzip detects your framework, excludes the noise, writes `codebase.zip` into `.contextzip/output/codebase/` and copies it to your clipboard. Paste it into your AI tool.
114
+
115
+ Some other common runs:
116
+
117
+ ```bash
118
+ contextzip --dry-run --verbose # preview every included/excluded file, write nothing
119
+ contextzip --git-changes # only what you've changed
120
+ contextzip --prompt "fix the login redirect bug" # let AI pick the relevant files
121
+ contextzip include src/ app/ # only these folders
122
+ contextzip include src/ .env # .env too, values redacted
123
+ contextzip exclude tests/ '*.snap' # everything except these
124
+ contextzip apply-zip # write the AI's changes back
125
+ ```
126
+
127
+ ## Features
128
+
129
+ ### Smart packaging
130
+
131
+ contextzip scans your project and recognises its stack from marker files such as `package.json`, `next.config.*`, `pyproject.toml`, `manage.py`, `Cargo.toml`, `go.mod` and `Gemfile`. It looks a couple of levels deep, so a monorepo with a Next.js frontend and a FastAPI backend gets **both** rule sets applied.
132
+
133
+ | Ecosystem | Examples of what's excluded |
134
+ |---|---|
135
+ | **Node.js / Next.js** | `node_modules/`, `.next/`, `dist/`, `build/`, `coverage/`, lockfiles, `*.min.js` |
136
+ | **Python / Django / FastAPI** | `__pycache__/`, `.venv/`, `*.pyc`, `.pytest_cache/`, `*.egg-info/` |
137
+ | **Rust** | `target/`, `Cargo.lock`, `*.rlib` |
138
+ | **Go** | `vendor/`, `bin/`, `go.sum` |
139
+ | **Ruby / Rails** | `vendor/bundle/`, `tmp/`, `log/`, `storage/`, built gems |
140
+
141
+ On top of the stack rules, contextzip also:
142
+
143
+ - respects your `.gitignore` (turn this off with `--no-gitignore`),
144
+ - flags large files (1 MB or more by default) and binary files before packaging,
145
+ - skips dangling symlinks and unreadable files, and tells you why,
146
+ - writes a plain-text report next to every ZIP listing what went in and what was left out.
147
+
148
+ ### Package only what changed
149
+
150
+ ```bash
151
+ contextzip --git-changes
152
+ ```
153
+
154
+ This packages only the files git reports as **staged, modified or untracked**. It's ideal for code review or "here's what I changed, what's wrong?" prompts. Deleted files, submodules and monorepo roots are handled for you, and the secret-exclusion rules still apply to files git tracks.
155
+
156
+ ### AI-powered file selection
157
+
158
+ ```bash
159
+ contextzip --prompt "add rate limiting to the login endpoint"
160
+ ```
161
+
162
+ Describe your task in plain language and [Gemini](https://ai.google.dev/) picks only the files that matter. The ZIP also includes a `prompt.txt` describing the task, so the AI tool you paste it into knows what you want.
163
+
164
+ - **Setup:** you need a free Gemini API key. contextzip walks you through it the first time you use `--prompt`, or you can set the `GEMINI_API_KEY` environment variable.
165
+ - **What is sent:** only the list of file **paths and sizes** that already passed the exclusion rules, plus your prompt. File contents never leave your machine.
166
+ - **Fallback:** if Gemini is rate-limited or unreachable, a local keyword-based selector takes over, so `--prompt` keeps working.
167
+ - **Model:** `gemini-2.5-flash-lite` by default.
168
+
169
+ ### Applying AI changes back
170
+
171
+ ```bash
172
+ contextzip apply-zip # picks up a ZIP from .contextzip/inbox/
173
+ contextzip apply-zip fix.zip # or point at one directly
174
+ contextzip apply-zip --dry-run # preview without writing anything
175
+ ```
176
+
177
+ Every ZIP contextzip creates gets a **local manifest** containing a hash of each file. It's stored next to the ZIP and never inside it, so the AI tool never sees it. When a ZIP comes back, `apply-zip` compares every file against that manifest:
178
+
179
+ | Status | Meaning | Action |
180
+ |---|---|---|
181
+ | **New** | File didn't exist before | Written |
182
+ | **Modified** | AI changed it, and you haven't touched it locally | Written |
183
+ | **Unchanged** | Identical to what's on disk | Skipped |
184
+ | **Drifted** | *You* edited it locally since zipping | ⚠️ Asks before overwriting |
185
+ | **Untracked** | Exists locally but wasn't in the original ZIP | ⚠️ Asks before overwriting |
186
+
187
+ `apply-zip` only adds and modifies files. **It never deletes anything.** It also unwraps the extra top-level folder that AI tools and "Download ZIP" buttons often add.
188
+
189
+ ### Terminal error watcher
190
+
191
+ ```bash
192
+ contextzip watch -- npm run dev
193
+ contextzip watch -- python manage.py runserver
194
+ contextzip watch -- python -m pytest --tb=short
195
+ ```
196
+
197
+ contextzip runs your command and watches its output. When a stack trace appears (Python, Django and Node.js/Next.js errors are recognised), it asks whether to package debug context. Press `D` and you get `debug-context.zip` containing:
198
+
199
+ - `prompt.txt`: an auto-generated description of the problem
200
+ - `terminal-error.txt`: the error output with ANSI codes and noise stripped out
201
+ - `source-files.zip`: the source files named in the stack trace
202
+
203
+ If you press Ctrl+C before packaging anything, you get one last chance to capture the whole session.
204
+
205
+ ### Visual config UI
206
+
207
+ ```bash
208
+ contextzip config --ui
209
+ ```
210
+
211
+ This opens a local browser tab where you can tick files and folders to always include or exclude, with a live preview of what the ZIP will contain. It saves to `.contextzip/config.json`. The server binds to `127.0.0.1` only, needs a random one-time session token and shuts itself down when you're done.
212
+
213
+ ## Command reference
214
+
215
+ | Command | What it does |
216
+ |---|---|
217
+ | `contextzip` | Detect the stack, exclude noise and package the project |
218
+ | `contextzip include PATH…` | Package **only** these paths |
219
+ | `contextzip exclude PATTERN…` | Package everything **except** these patterns |
220
+ | `contextzip --prompt "task"` | Let Gemini pick only the files relevant to a task |
221
+ | `contextzip --git-changes` | Package only modified, staged and untracked files |
222
+ | `contextzip apply-zip [ZIP]` | Write an AI-returned ZIP back into your project, safely |
223
+ | `contextzip watch -- COMMAND` | Run a command and package debug context when an error appears |
224
+ | `contextzip config …` | Gemini key, workspace location and the visual config UI |
225
+ | `contextzip update` | Check PyPI for a newer release and update in place |
226
+
227
+ **Run flags** work on `contextzip`, `include` and `exclude`:
228
+
229
+ | Flag | Short | Description |
230
+ |---|---|---|
231
+ | `--include PATH` | `-i` | Only include files under these paths. Naming an excluded path (like `.env`) brings it back. Repeatable. |
232
+ | `--exclude PATTERN` | `-e` | Extra exclusion patterns (gitignore syntax). Repeatable. |
233
+ | `--prompt TEXT` | `-p` | Let Gemini select files relevant to this task. |
234
+ | `--git-changes` | | Only include files git reports as changed. |
235
+ | `--dry-run` | `-n` | Show what would be included without creating the ZIP. |
236
+ | `--output FILE` | `-o` | Write the ZIP to this exact path. |
237
+ | `--no-clipboard` | | Don't copy the ZIP to the clipboard. |
238
+ | `--no-gitignore` | | Ignore `.gitignore` and use only the built-in rules. |
239
+ | `--verbose` | `-v` | List every included and excluded file. |
240
+
241
+ Every command supports `-h` / `--help`, and `contextzip --version` prints the installed version.
242
+
243
+ For every flag of every subcommand (`apply-zip`, `watch`, `config`, `update`), see **[CLI.md](https://github.com/akadeepesh/contextzip/blob/main/CLI.md)** or the [online CLI reference](https://contextzip.vercel.app/cli).
244
+
245
+ ## Configuration
246
+
247
+ contextzip has two config files, and both are optional.
248
+
249
+ ### Project config: `.contextzip/config.json`
250
+
251
+ This holds per-project settings. Edit it by hand or with `contextzip config --ui`. Every key is optional:
252
+
253
+ ```jsonc
254
+ {
255
+ "always_include": ["docs/architecture.md"], // force-include, even if a rule or .gitignore excludes it
256
+ "always_exclude": ["*.snap", "fixtures/"], // a standing --exclude on every run
257
+ "workspace_location": "git-root", // "git-root" | "cwd" | "/some/path"
258
+ "ai": {
259
+ "enabled": true,
260
+ "max_files": 10, // cap on files the AI may select
261
+ "prompt_template": "We use pytest, not unittest." // prepended to every prompt.txt
262
+ },
263
+ "limits": {
264
+ "max_file_size_mb": 1, // threshold for "large file" warnings
265
+ "redact_secrets": false // scan included files and mask secret-looking values
266
+ },
267
+ "applied_zip_retention": 1, // past apply-zip archives to keep
268
+ "cleanup": { "enabled": true, "keep_recent": 1 },
269
+ "webui": { "auto_open": true, "port": null }
270
+ }
271
+ ```
272
+
273
+ `.contextzip/` is fully gitignored by default. If your team wants to share these settings, commit the file explicitly with `git add -f .contextzip/config.json`.
274
+
275
+ ### Personal config
276
+
277
+ Your Gemini API key and personal defaults live outside the project, so they're never committed:
278
+
279
+ | OS | Location |
280
+ |---|---|
281
+ | Linux / macOS | `~/.config/contextzip/config.json` (or `$XDG_CONFIG_HOME/contextzip/`) |
282
+ | Windows | `%APPDATA%\contextzip\config.json` |
283
+
284
+ ```bash
285
+ contextzip config # show the current configuration
286
+ contextzip config --reset-key # clear the Gemini key and set it up again
287
+ contextzip config --set-workspace cwd # put .contextzip/ in the current directory
288
+ contextzip config --show-key-path # print the config file location
289
+ ```
290
+
291
+ The full option-by-option guide is at [contextzip.vercel.app/configuration](https://contextzip.vercel.app/configuration).
292
+
293
+ ## What is always excluded
294
+
295
+ These patterns apply to **every** project, whatever its stack or `.gitignore` says, and in `--git-changes` mode too:
296
+
297
+ - **Secrets & credentials:** `.env`, `.env.*`, `*.pem`, `*.key`, `*.p12`, `*.pfx`, `*.jks`, `*.keystore`, `*.ppk`, SSH private keys (`id_rsa`, `id_ed25519`, …), `.npmrc`, `.netrc`, `.pypirc`, `.pgpass`, Docker auth config, `.aws/credentials`, service-account and `*credentials*.json` files, kubeconfigs
298
+ - **Infrastructure state:** `*.tfstate`, `.terraform/`
299
+ - **Version control & editors:** `.git/`, `.svn/`, `.hg/`, `.vscode/`, `.idea/`, swap files, `.DS_Store`
300
+ - **Logs, caches & temp files:** `*.log`, `logs/`, `.cache/`, `tmp/`, `*.tmp`, `*.bak`
301
+ - **Binaries & media:** executables, shared libraries, images, video, audio and archives
302
+ - **Project boilerplate:** `CHANGELOG`, `LICENSE`, `CONTRIBUTING`, `SECURITY.md`, `CODE_OF_CONDUCT.md`, GitHub issue/PR templates
303
+
304
+ To bring one back, name it explicitly with `contextzip include .env`, list it under `always_include` in the project config, or tick it in `contextzip config --ui`. `--exclude` and `.gitignore` can't bring them back, and naming a folder like `src/` doesn't pull in the secret files inside it.
305
+
306
+ **Secret files you include on purpose are always redacted.** If you include your `.env` so the AI can see which variables your app expects, every key and comment is kept but every value becomes `[REDACTED]`:
307
+
308
+ ```bash
309
+ # .env on disk # .env in the ZIP
310
+ DATABASE_URL=postgres://u:pw@db/app DATABASE_URL=[REDACTED]
311
+ export API_KEY="sk-live-…" # prod export API_KEY="[REDACTED]" # prod
312
+ ```
313
+
314
+ Other secret files (private keys, credential files) get a secret-pattern scan. Binary ones like `.p12` can't be redacted, so they're left out. All of this happens whatever your other settings say.
315
+
316
+ For extra safety, set `limits.redact_secrets: true` to also mask API keys, tokens, JWTs and private-key blocks hardcoded inside ordinary files that get included. Every run's report lists what was redacted.
317
+
318
+ > **Tip:** before sharing a sensitive project, run `contextzip --dry-run --verbose` to see exactly what will go into the ZIP.
319
+
320
+ ## Where files go
321
+
322
+ contextzip keeps everything in a `.contextzip/` folder at your git root (change this with `contextzip config --set-workspace`):
323
+
324
+ ```text
325
+ .contextzip/
326
+ ├── output/
327
+ │ ├── codebase/ codebase.zip + manifest + report (contextzip)
328
+ │ ├── git-changes/ changes.zip + manifest + report (--git-changes)
329
+ │ ├── prompt/ vibe.zip + manifest + report (--prompt)
330
+ │ └── watch/ debug-context.zip (contextzip watch)
331
+ ├── inbox/ drop AI-returned ZIPs here for apply-zip
332
+ └── config.json project config (optional)
333
+ ```
334
+
335
+ Old outputs are cleaned up automatically, and only the most recent set is kept. You can change this with the `cleanup` setting.
336
+
337
+ ## Python API
338
+
339
+ contextzip is also a library. The functions behave like the CLI but return plain Python objects and raise exceptions instead of printing.
340
+
341
+ ```python
342
+ from contextzip import get_files, get_git_changes, create_zip, apply_zip, detect_ecosystem
343
+
344
+ # All project files, filtered by .gitignore and the built-in rules
345
+ collection = get_files(include=["src/"], exclude=["*.log"])
346
+ for path in collection.files: # plain pathlib.Path objects
347
+ print(path)
348
+
349
+ # Only git-changed files, zipped
350
+ changes = get_git_changes()
351
+ pkg = create_zip(changes, output="/tmp/changes.zip")
352
+ print(f"Packed {pkg.file_count} files → {pkg.zip_path}")
353
+
354
+ # What stack is this?
355
+ print(detect_ecosystem("."))
356
+ ```
357
+
358
+ | Function | Returns |
359
+ |---|---|
360
+ | `get_files(path=None, *, include=None, exclude=None, …)` | `FileCollection` of all project files after filtering |
361
+ | `get_git_changes(path=None, *, use_project_config=True)` | `FileCollection` of staged, modified and untracked files |
362
+ | `create_zip(collection, output=…)` | `PackageResult` with the ZIP path, file count and sizes |
363
+ | `apply_zip(zip_path=None, …)` | `ApplyResult` describing what was written |
364
+ | `detect_ecosystem(path=None)` | Detected ecosystem information |
365
+
366
+ All exceptions inherit from `ContextzipError`: `NotARepositoryError`, `GitNotFoundError`, `GitCommandError`, `NoFilesError` and `ZipNotFoundError`.
367
+
368
+ For full signatures, see [contextzip.vercel.app/cli#python-api](https://contextzip.vercel.app/cli#python-api).
369
+
370
+ ## Privacy & security
371
+
372
+ - **Local by default.** Packaging, `apply-zip`, `watch` and the config UI never make network requests.
373
+ - **Network use is opt-in and limited to two features:**
374
+ - `--prompt` sends file paths, sizes and your prompt to the Gemini API. File contents are never sent.
375
+ - `contextzip update` asks PyPI for the latest version number.
376
+ - **No telemetry.** Nothing is collected or phoned home.
377
+ - **Manifests stay local.** `apply-zip` manifests are written next to the ZIP and never inside it.
378
+ - **Secrets are excluded or redacted.** See [What is always excluded](#what-is-always-excluded).
379
+
380
+ Found a vulnerability? Please follow [SECURITY.md](https://github.com/akadeepesh/contextzip/blob/main/SECURITY.md) and report it privately rather than in a public issue.
381
+
382
+ ## Platform support
383
+
384
+ | | Windows | macOS | Linux |
385
+ |---|---|---|---|
386
+ | Packaging, `apply-zip`, config | ✅ | ✅ | ✅ |
387
+ | ZIP copied to clipboard as a file | ✅ native (`CF_HDROP`) | ✅ via Finder | ✅ built-in X11 owner (works under XWayland), or `wl-copy` / `xclip` |
388
+ | `contextzip watch` | ✅ (best in Windows Terminal / VS Code) | ✅ | ✅ |
389
+
390
+ If the clipboard can't be used, contextzip opens the output folder with the ZIP selected and tells you why. Use `--no-clipboard` to skip this step entirely.
391
+
392
+ ## Contributing
393
+
394
+ Contributions are welcome, especially **new framework rule sets** and edge-case fixes. Not up for writing code? [Request a feature](https://contextzip.vercel.app/request-feature) or [request your language](https://contextzip.vercel.app/request-language). Both turn into GitHub issues ranked by 👍. To set up a local copy:
395
+
396
+ ```bash
397
+ git clone https://github.com/akadeepesh/contextzip
398
+ cd contextzip
399
+ python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
400
+ pip install -e .
401
+ contextzip --version
402
+ ```
403
+
404
+ Adding a new language takes three small steps: a `PATTERNS` list in `contextzip/rules/`, one registry entry and one detection rule. [CONTRIBUTING.md](https://github.com/akadeepesh/contextzip/blob/main/CONTRIBUTING.md) walks through it, along with PR conventions. Please open an issue before starting a large PR.
405
+
406
+ ## License
407
+
408
+ [MIT](https://github.com/akadeepesh/contextzip/blob/main/LICENSE) © Deepesh