Files

17 KiB

contextzip CLI reference

Every command and flag in one place. cz is a short alias for contextzip — they are the same program.

Keeping this file current: whenever you add, rename or remove a command or flag in contextzip/cli.py, update this file in the same commit and mention it in the CHANGELOG.md entry. contextzip --help and contextzip <command> --help are always the source of truth.

Contents

Quick reference

Command What it does
contextzip Detect the stack, exclude noise, package the project
contextzip include PATH… Package only these paths
contextzip exclude PATTERN… Package everything except these patterns
contextzip --prompt "task" Let Gemini pick only the files relevant to a task
contextzip --git-changes Package only modified / added / untracked files
contextzip apply-zip [ZIP] Write an AI-returned ZIP back into your project, safely
contextzip watch -- COMMAND Run a command and package debug context when an error appears
contextzip config … Gemini key, workspace location, visual include/exclude UI
contextzip update Check PyPI for a newer release and update in place

Run flags

These flags work on the main command and on include and exclude. Flags go after the verb, like git or docker: contextzip exclude CHANGELOG.md --dry-run --verbose.

Flag Short Description
--include PATH -i Only include files under these paths (relative to the project root). Naming a path the rules exclude, like .env, brings it back. Repeatable. Same as contextzip include.
--exclude PATTERN -e Extra exclusion patterns on top of the automatic rules (gitignore syntax). Repeatable. Same as contextzip exclude.
--prompt TEXT -p Describe your task in plain language; Gemini selects only the relevant files. Needs a free Gemini API key (you're guided through setup on first use).
--dry-run -n Show what would be included without creating the ZIP.
--output FILE -o Write the ZIP directly to FILE, bypassing the .contextzip/ workspace.
--no-clipboard Skip the clipboard step after creating the ZIP.
--no-gitignore Ignore the project's .gitignore (use only the built-in rules).
--git-changes Only include files git reports as modified, added or untracked. The project must be inside a git repository.
--verbose -v Show every included and excluded file.
--here Only package the folder you're in. Paths in the ZIP stay relative to the project root.

--include and --exclude (and the include / exclude subcommands) also work together with --git-changes, and are combined with always_include / always_exclude from .contextzip/config.json.

Project root

Every command works from the project root, wherever you run it from, like git does. Run cz inside frontend/ of a monorepo and the workspace stays at the root (no frontend/.contextzip/), the ZIP's paths are root-relative, and apply-zip puts files back in the right place.

The root is, first match wins:

  1. CONTEXTZIP_ROOT, if set.
  2. The outermost folder (not above your home folder) that is a git repository (.git folder or file) or has a .contextzip/config.json. Outermost on purpose: tools like create-next-app run git init inside the folder they generate, which leaves a nested frontend/.git in your monorepo.
  3. The outermost folder with an existing .contextzip/ workspace.
  4. The current folder.

Paths you type are relative to where you are, like git add: from frontend/, cz include src/ means frontend/src/. Add --here to package just the current folder. contextzip config shows which root was picked and why. --git-changes also reads repositories nested inside the root (an embedded frontend/.git, or submodules).

contextzip

Run from your project root. contextzip detects your stack, applies smart exclusions and writes a ZIP into .contextzip/. When it finishes, the ZIP is placed on your clipboard as a real file, so you can paste it straight into Claude, ChatGPT or any AI tool's upload box. If the clipboard can't be used, it opens the folder instead and tells you why.

contextzip                                  # package the whole project
contextzip --dry-run --verbose              # preview, listing every file
contextzip --git-changes                    # only what you've changed
contextzip --prompt "fix the login redirect bug"
contextzip -o ~/Desktop/project.zip         # write to an exact path
contextzip --no-clipboard                   # build the ZIP, skip clipboard

contextzip include

Package only the specified paths and skip everything else.

contextzip include PATH…  [run flags]

contextzip include src/ app/
contextzip include src/ app/ --dry-run
contextzip include src/ .env            # bring back a file the rules exclude
contextzip include dist/                # or a whole excluded folder

Paths match at folder boundaries: src matches src/index.ts but not src2/index.ts. Leading ./ or .\ is ignored.

Naming an excluded path brings it back. If a path you name is itself excluded (by the built-in rules, .gitignore or always_exclude), it is included anyway, because you asked for it explicitly. Inside a named folder, excluded folders nested deeper are still skipped (include dist/ leaves out dist/node_modules/). Naming an ordinary folder only narrows the run: include src/ does not pull in src/.env. Secret files brought back this way, such as .env, keep their keys but have every value replaced with [REDACTED]. The same applies to --include / -i.

contextzip exclude

Exclude specific files or patterns and package everything else. Patterns use gitignore syntax; a folder matches with or without a trailing slash (.github and .github/ both work).

contextzip exclude PATTERN…  [run flags]

contextzip exclude CHANGELOG.md CONTRIBUTING.md LICENSE
contextzip exclude .github/ tests/ '*.log'
contextzip exclude CHANGELOG.md --dry-run --verbose
contextzip exclude .github/ CHANGELOG.md --output ~/Desktop/out.zip

Quote patterns that contain * so your shell doesn't expand them first.

contextzip apply-zip

Apply an AI-returned ZIP back into your project.

contextzip apply-zip [ZIP] [--manifest PATH] [-n] [-v] [--review | --editor | --safe-only | -y]
Argument / flag Short Description
ZIP Path to the returned ZIP. Optional: if omitted, contextzip looks in .contextzip/inbox/. An explicit path overrides the inbox.
--manifest PATH Snapshot to compare against, instead of the one that best matches the ZIP.
--dry-run -n Show what would change; write nothing.
--verbose -v List every file and what will happen to it.
--review Decide file by file in a local browser page with side-by-side diffs.
--editor Resolve files that need a decision in VS Code (or Cursor, Windsurf, VSCodium).
--safe-only Apply only the safe changes; leave the rest untouched. For scripts and CI.
--yes -y Apply everything without asking. Where you and the AI disagree, the AI's version wins. Never removes files.
--snapshot ID The snapshot this reply answers (e.g. 14). Usually found automatically.
--remove-moved Remove the old copy of files the AI moved (only if you haven't changed them).
--allow-delete Delete files the AI asked to delete in CONTEXTZIP.md (only if you haven't changed them).
contextzip apply-zip                    # from .contextzip/inbox/, asks when something needs a decision
contextzip apply-zip fix.zip            # a ZIP anywhere on disk
contextzip apply-zip --dry-run -v       # see exactly what would happen
contextzip apply-zip --review           # decide in the browser
contextzip apply-zip --editor           # three-way merge in VS Code
contextzip apply-zip --safe-only        # CI: only the safe changes

Where each file goes. The returned ZIP doesn't need to match your layout. Each file is matched to the project by its longest shared path suffix, so a ZIP wrapped in an extra folder, made relative to a subfolder (src/... for frontend/src/...), flattened to bare names, or using backslash separators still lands correctly. The layout learned from files that clearly match is applied to brand-new files too. A name that fits several files is settled by content; if it's still unclear the file is marked ambiguous and never written on a guess. __MACOSX/, .DS_Store and contextzip's own prompt.txt are ignored.

What it compares against. Every ZIP contextzip makes gets a local manifest, never uploaded. apply-zip picks the manifest that best matches the returned ZIP, not just the newest, so an unrelated run in between (or -o) doesn't confuse it. Each file is then compared three ways: what you sent, what's on disk now, and what came back.

Status Meaning Default
new The file doesn't exist yet written
modified Only the AI changed it written
merged You both changed it in different places — three-way merged written
unchanged Already matches, including "you already applied this" skipped
conflict You both changed the same lines needs your call
drifted You changed it and it can't be merged (binary, or the original ZIP is gone) needs your call
deleted You deleted it after zipping needs your call
untracked Exists here but wasn't in the ZIP you sent needs your call
partial The AI returned a cut-down file (// ... rest unchanged) needs your call
ambiguous Can't tell which file it belongs to needs your call
moved The AI moved or renamed it (declared in CONTEXTZIP.md, or near-identical content) new path written; old file kept unless you say so
delete-requested The AI asked to delete it in CONTEXTZIP.md needs its own yes

Snapshots. The snapshot is found from the CONTEXTZIP.md the reply echoes back, or, if it didn't, by matching content against your snapshots. Since every snapshot keeps a copy of what was sent, merging works even if you've packaged again since.

Line endings never count as a change, and text is written back with the local file's line endings and BOM. Secret files that were redacted on the way out are merged against the redacted copy, so your real values are kept and a [REDACTED] placeholder is never written over them.

When something needs a decision, apply-zip asks: apply the safe changes and leave the rest, review in the browser, resolve in your editor, apply everything, or quit. Without a terminal to ask (CI), it writes nothing unless you pass --safe-only or --yes. If anything is left undecided, the ZIP stays in the inbox so you can run apply-zip again. Only adds and modifies files — nothing is ever deleted.

contextzip watch

Run a command, watch its output and package debug context when an error appears.

contextzip watch -- COMMAND [ARGS]…

contextzip watch -- npm run dev
contextzip watch -- python manage.py runserver
contextzip watch -- python -m pytest --tb=short

The -- separates contextzip's own arguments from your command. When an error is detected you're prompted: [D] package debug context, [S] skip. Pressing D writes .contextzip/output/watch/debug-context.zip containing:

  • prompt.txt — an auto-generated task description
  • terminal-error.txt — the cleaned error output
  • source-files.zip — the source files named in the stack trace (files you've put in always_exclude are left out)

On Ctrl+C, if nothing was packaged yet, you're offered one last chance to capture the whole session.

Notes:

  • Works best with dev servers that don't read stdin interactively (npm run dev, manage.py runserver, cargo watch, …).
  • On Windows, colour passthrough may be limited; Windows Terminal or the VS Code terminal work best.
  • No PTY emulation is used. If your process needs a real TTY to behave correctly, run it directly instead.

contextzip config

Manage configuration. With no flags it shows the current configuration status (including whether a Gemini key is stored or comes from the GEMINI_API_KEY environment variable).

contextzip config [--reset-key] [--set-workspace LOCATION] [--reset-workspace]
                  [--show-key-path] [--ui]
Flag Description
--reset-key Clear the stored Gemini API key and run the setup prompt again.
--set-workspace LOCATION Set your personal default for where .contextzip/ lives: git-root, cwd, or a path.
--reset-workspace Clear your personal workspace location override.
--show-key-path Print the path of the config file and exit.
--ui Open a local browser tab to set include/exclude rules visually and write .contextzip/config.json.
contextzip config --reset-key               # clear Gemini key, re-onboard
contextzip config --set-workspace cwd       # always use ./.contextzip here
contextzip config --set-workspace git-root  # back to the default
contextzip config --set-workspace ~/zips    # a fixed custom location
contextzip config --reset-workspace         # clear the personal override
contextzip config --show-key-path           # print the config file location
contextzip config --ui                      # visually set include/exclude

A workspace location can also be pinned for a whole team by committing .contextzip/config.json at the project root, for example {"workspace_location": "git-root"}. A project config takes priority over your personal setting.

contextzip snapshots

List this project's snapshots: number, token, mode, file count, age, and whether a reply has been applied.

contextzip snapshots

Every package is kept as a numbered snapshot in .contextzip/snapshots/ (local, never uploaded): a copy of the ZIP plus a manifest of what was sent. Each ZIP's CONTEXTZIP.md names its snapshot, e.g. Snapshot: 14-k3f9a2. Snapshots are kept while they're among the newest snapshots.keep (10), younger than snapshots.max_age_days (14), or still awaited by a reply in the inbox.

CONTEXTZIP.md

A short file added to every ZIP for the AI that receives it: the project, the snapshot ID, and how to reply so apply-zip can put the answer back cleanly — only changed files, complete contents, the same paths, [REDACTED] values left alone, and moves or deletions listed under Changes (moved: a -> b, deleted: x). Turn it off per project with "zip_guide": false or in contextzip config --ui.

contextzip update

Check PyPI for a newer release and update in place.

contextzip update [--check] [--yes]
Flag Short Description
--check Only report the current and latest version; install nothing.
--yes -y Skip the confirmation prompt and update immediately if an update is available.
contextzip update            # check, then confirm before updating
contextzip update --yes      # update immediately if one is available
contextzip update --check    # just report current vs latest
cz update                    # same thing, short alias

It detects whether contextzip was installed with pip, pipx or uv tool and re-runs the matching one, upgrading the same interpreter that is currently running (never a different pip that happens to be first on your PATH). The manual equivalent is pip install --upgrade contextzip.

Global flags

Flag Short Description
--help -h Show help. Works on every command: contextzip apply-zip -h.
--version Print the installed version.

Where files go

Path Contents
.contextzip/output/ ZIPs contextzip creates, plus the manifests used by apply-zip
.contextzip/output/watch/ Debug packages from contextzip watch
.contextzip/inbox/ Where apply-zip looks for a returned ZIP when you don't pass a path
.contextzip/config.json Project config: always_include, always_exclude, workspace_location, ai, size limits
.contextzip/snapshots/ Numbered snapshots: a copy of each ZIP you sent and its manifest — what apply-zip merges against

Where .contextzip/ itself lives defaults to the git root; see contextzip config --set-workspace.