178 Commits
Author SHA1 Message Date
akadeepeshandClaude Opus 5.5 e499b7e453 docs: move docs links to www.contextzipcli.com
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 02:35:51 +05:30
akadeepeshandClaude Opus 5.5 dc4659ae72 ci: require the test suite to pass before publishing to PyPI
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 16:45:28 +05:30
akadeepeshandClaude Opus 5.5 517e7eca4e test: add test suite and cross-platform CI
Covers project-root detection, path matching, three-way merges, apply-zip
end to end, snapshots and CONTEXTZIP.md, workspace detection and git
changes in nested repos. Runs on Windows, macOS and Linux with Python
3.9, 3.12 and 3.13: python -m unittest discover -s tests -t .

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 16:43:08 +05:30
akadeepeshandClaude Opus 5.5 a93c397bdc chore(release): 0.5.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v0.5.0
2026-10-19 16:40:12 +05:30
akadeepeshandClaude Opus 5.5 dee0784c58 chore: keep line endings LF with .gitattributes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 16:40:12 +05:30
akadeepeshandClaude Opus 5.5 e14c3d569d docs: document project root, apply-zip review, snapshots and CONTEXTZIP.md
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 16:40:12 +05:30
akadeepeshandClaude Opus 5.5 5eb6644027 feat: monorepo-aware project root, rebuilt apply-zip and versioned snapshots
Project root
- Every command (packaging, --git-changes, apply-zip, watch, config UI)
  now resolves one project root and works from there, wherever it's run.
  The outermost git repo wins, so a nested frontend/.git from
  create-next-app no longer hijacks it; .git files (worktrees, submodules)
  count; CONTEXTZIP_ROOT overrides. Typed paths are cwd-relative like
  `git add`. New --here flag packages only the current folder.
- Non-git monorepos (sibling repos, nothing at the top) are offered as the
  root once; the answer is remembered. Submodules get a notice.
- --git-changes reads nested repos and uses NUL-separated output.
- watch runs the command where you ran it and resolves trace paths there.
- Workspace packages declared by npm/yarn/pnpm, lerna, Cargo and go.work
  are detected at any depth.

apply-zip
- Files are matched by path suffix, so wrapped, subfolder-relative,
  flattened or backslash ZIPs land correctly; new files follow siblings.
- Three-way merge against what was sent; new statuses merged, conflict,
  partial, deleted, ambiguous, moved and delete-requested. Line endings
  never count as a change; local EOL and BOM are kept.
- Redacted secret files are merged so placeholders never overwrite real
  values.
- Choose per run: safe changes only, browser review (--review), editor
  three-way merge (--editor), or everything (--yes). Files are only
  removed with an explicit OK (--remove-moved / --allow-delete).

Snapshots
- Every package is kept as a numbered snapshot in .contextzip/snapshots/
  so replies merge against exactly what was sent, even after repackaging.
- Every ZIP carries CONTEXTZIP.md with the snapshot ID and reply rules;
  replies that echo it are matched exactly. `contextzip snapshots` lists
  them; `"zip_guide": false` turns the file off.

Also: heuristic AI selections are labelled as such, create_zip() in the
Python API honours redact_secrets, and pathspec's deprecated gitwildmatch
factory is replaced by GitIgnoreSpec.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 16:40:12 +05:30
akadeepesh 81ee358031 docs: clarify fallback behavior for Gemini API in README 2026-10-19 06:16:30 +05:30
akadeepeshandClaude Opus 5.5 82393ea6f0 chore(release): 0.4.7
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v0.4.7
2026-10-19 05:01:40 +05:30
akadeepeshandClaude Opus 5.5 d75406086f docs: document bringing back excluded paths with contextzip include
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 05:01:40 +05:30
akadeepeshandClaude Opus 5.5 4c727633c6 fix(cli): point the unknown-language hint at the request-language page
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 05:01:40 +05:30
akadeepeshandClaude Opus 5.5 87561e6315 feat(include): bring back excluded paths named explicitly with --include
`contextzip include .env` or `include dist/` now includes paths the rules
exclude instead of matching nothing. Nested excluded folders still apply,
and naming an ordinary folder doesn't pull in secret files inside it.
Include paths also accept a leading ./ or .\. The CLI and report list
files brought back this way.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 05:01:39 +05:30
akadeepeshandClaude Opus 5.5 8052318063 docs: document secret-file redaction and refresh security policy
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 04:44:37 +05:30
akadeepeshandClaude Opus 5.5 550c5462a1 fix(report): list files left out of the ZIP and group repeated redactions
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 04:44:37 +05:30
akadeepeshandClaude Opus 5.5 842e689175 feat(redact): always redact secret files included via always_include
.env files keep keys and comments but every value becomes [REDACTED];
other secret files get the pattern scan; binary ones are left out.
Applies regardless of limits.redact_secrets, including watch's debug ZIP.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 04:44:37 +05:30
akadeepeshandClaude Opus 5.5 98d89eefeb refactor(rules): split secret-file patterns into SECRET_PATTERNS
PATTERNS still includes them, so default exclusions are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 04:44:36 +05:30
akadeepesh 22c36355f1 docs: enhance README with detailed installation instructions and feature overview 2026-10-19 04:20:35 +05:30
akadeepesh 6d7ddc175a docs: update README and add CLI reference documentation 2026-10-10 10:52:33 +05:30
akadeepesh 5d7d801670 chore(release): 0.4.6 v0.4.6 2026-10-07 21:22:26 +05:30
akadeepesh a9fd486e41 fix(cli): say so when the ZIP couldn't be copied to the clipboard
A fallback to opening the folder used to print nothing, so a failed clipboard copy was invisible. It now prints a warning and, when known, how to fix it.
2026-10-07 21:22:25 +05:30
akadeepesh 88bde9fff7 fix(clipboard): put the ZIP on the clipboard as a real file on Windows and Linux
Windows had no clipboard step (it went straight to Explorer). Linux wrote the ZIP's raw bytes as application/zip, which browsers ignore, and only if xclip was installed.

Windows: set CF_HDROP via ctypes plus Preferred DropEffect, read it back with DragQueryFileW to verify; fall back to PowerShell Set-Clipboard -LiteralPath (path passed via env var); then Explorer. Linux: wl-copy (if present on Wayland) -> built-in X11 owner -> xclip (if present), all setting text/uri-list and read back before reporting success. xclip/wl-copy output is no longer captured, so they can't block the CLI.

Also: Explorer /select is now a single quoted command line (paths with spaces/commas), headless/SSH Linux sessions print the path instead of launching xdg-open, and macOS escapes quotes in the path. ClipboardResult gains an optional hint field.
2026-10-07 21:22:25 +05:30
akadeepesh ae0f6772c3 feat(clipboard): add pure-Python X11 clipboard owner for Linux
Owns the CLIPBOARD selection through the raw X protocol (stdlib only), so pasting a file works without xclip or any other system package.

Serves text/uri-list (read by browsers on paste), x-special/gnome-copied-files and application/x-kde-cutselection, answers TARGETS, and exits when another app takes the clipboard. Reads MIT-MAGIC-COOKIE from XAUTHORITY / ~/.Xauthority. Signals 'ready' once it owns the selection so the launcher can verify the copy.
2026-10-07 21:22:24 +05:30
akadeepesh c927bca5fb chore(version): bump version to 0.4.5 v0.4.5 2026-10-07 11:17:54 +05:30
akadeepesh f922945729 chore(gitignore): clean up contextzip output file comments and add local_docs 2026-10-07 11:17:49 +05:30
akadeepesh f213a3c282 feat(api): enhance git change retrieval with project config support 2026-10-07 11:17:15 +05:30
akadeepesh e7b62f359e feat(cli): enhance exclusion pattern handling and improve user feedback 2026-10-07 11:17:08 +05:30
akadeepesh 1f920f81e5 feat(process_buffer): add support for always_include and always_exclude patterns in file path filtering 2026-10-07 11:16:01 +05:30
akadeepesh 39a3b3c616 feat(filters): enhance file resolution with manual include/exclude support 2026-10-07 11:15:56 +05:30
akadeepesh a466e0cdb4 fix(watcher): respect manual include/exclude settings in debug context packaging 2026-10-07 11:15:50 +05:30
Deepesh KumarandGitHub f3831728b5 Update README with asset link and comment out image
Added a link to an asset and commented out an image tag in the README.
2026-10-05 04:17:56 +05:30
akadeepesh 7f01c450bb chore(release): bump version to 0.4.4 v0.4.4 2026-09-22 02:44:07 +05:30
akadeepesh 575f915ed0 fix(inbox): add README and ensure inbox directory is created for apply-zip 2026-09-22 02:39:50 +05:30
akadeepesh 7c33f19b8e fix(docs): update apply-zip section to mention manifest diffing for improved clarity 2026-09-22 02:32:49 +05:30
akadeepesh ad47ab87f1 fix(cleanup): remove backup handling and references from apply-zip and related components 2026-09-22 02:32:37 +05:30
akadeepesh c21079d295 fix(cleanup): add handling for loose apply-report files in inbox to prevent accumulation 2026-09-22 02:27:31 +05:30
akadeepesh 63c19a959d fix(report): write apply-zip report to .contextzip/inbox/ to avoid cluttering project directory 2026-09-22 02:26:09 +05:30
akadeepesh e244810ec1 fix(applier): fall back to on-disk layout when manifest can't settle wrapper-strip
Manifest-based match-rate comparison ties at 0% (both stripped and
unstripped) whenever the freshest manifest is scoped to a subset of the
project — most commonly a git-diff manifest from output/git-changes/,
which only ever tracked files touched in one prior change. A zip of
otherwise-legitimate new files then looks equally unmatched either way,
so the previous logic played it safe and left the wrapper folder in
place, dumping it verbatim into the project.

Now, when the manifest signal ties, fall back to comparing top-level
path segments against the project's real, current directory layout
(app/, components/, lib/, etc.) instead. Confirmed against a
reproduction of the exact reported case.
2026-09-20 15:48:19 +05:30
akadeepesh 4f185984e1 chore(changelog): update changelog for version 0.4.3 with new features and fixes v0.4.3 2026-09-20 11:56:47 +05:30
akadeepesh 4e52122e42 chore(release): bump version to 0.4.3 2026-09-20 11:56:37 +05:30
akadeepesh 777e798041 fix(webui): auto-close the config UI tab after saving
The success overlay already told the user they could close the tab,
but nothing ever tried to. Calls window.close() shortly after the save
+ shutdown round-trip completes. Browsers permit scripted close on
tabs whose entire session history is a single page, which the config
UI always is, so this closes cleanly and drops the user back to their
terminal; if a browser still blocks it, the existing on-screen message
remains as the manual fallback.
2026-09-20 11:56:37 +05:30
akadeepesh 20490a75e8 feat(cli): add contextzip update / cz update self-update command
Queries PyPI for the latest published version and compares it against
the running __version__. When a newer release exists, re-invokes
whichever installer matches how contextzip was installed (pip, pipx,
or uv tool), always against the currently running interpreter rather
than a bare 'pip' off PATH.

  cz update            # check, then confirm before updating
  cz update --yes      # update immediately if available
  cz update --check    # report versions only, install nothing

Never raises on network failure — a bad connection or PyPI hiccup
degrades to a clear 'couldn't check' message instead of a traceback.
2026-09-20 11:56:37 +05:30
akadeepesh 6ac6b85070 fix(applier): stop skipping wrapper-strip when project has a same-named folder
apply-zip's wrapper-folder detection refused to strip a zip's outer
folder whenever the project already had a real directory of that same
name — which backfires on the single most common shape of AI-returned
zip: the whole project wrapped in a folder named after the project (or
its own package dir), e.g. 'project/' or 'contextzip/contextzip/...'.
Since the project's real package dir almost always shares that name,
the guard treated the wrapper as legitimate structure and dumped a
nested copy at the project root instead of updating the real files.

Now, whenever a manifest is available, the decision is made by
comparing manifest match-rate with vs. without stripping (ground
truth about what paths this project actually has) instead of
inferring intent from what merely exists on disk. Falls back to the
old on-disk heuristic only when no manifest exists to check against.

Fixes the case where apply-zip silently mis-applies a returned zip.
2026-09-20 11:56:37 +05:30
akadeepesh c84ba3367b chore: update version to 0.4.2 and enhance changelog with limits.redact_secrets enforcement v0.4.2 2026-09-03 08:46:50 +05:30
akadeepesh a858f39359 fix: stop gitignoring an exception for config.json
.contextzip/.gitignore now ignores the entire workspace with no
exceptions (previously carved out !config.json so it stayed
trackable by default). config.json is local by default like
everything else in the workspace; a team that wants to share it now
has to explicitly \`git add -f .contextzip/config.json\`, rather than
that happening automatically on a plain \`git add\`.

The core of this change (the .gitignore contents themselves, and the
docstrings in packager.py / project_config.py) landed in the previous
commit since those files were already being touched for redact_secrets.
This commit is the remaining two files whose only change is this.
2026-09-03 01:34:01 +05:30
akadeepesh fa247e34e1 feat: implement limits.redact_secrets enforcement
Previously persisted by config.py / the config UI but never actually
enforced (flagged as a known limitation as of 0.4.0). Text files
already going into the archive are now scanned for secret-shaped
values and matched values are replaced with [REDACTED] before
writing.

- New redact.py: curated high-precision patterns (AWS/Google/GitHub/
  Slack/Stripe/Anthropic/OpenAI keys, JWTs, private-key blocks, and a
  conservative generic key/secret/token/password assignment pattern)
  with placeholder-value filtering (changeme, xxxxxxxx, <placeholder>,
  ${ENV_VAR} interpolation are left alone).
- packager.py: new _write_member() helper shared by create_zip() and
  create_zip_silent(); only scans files already known (via
  ResolveResult) to be text and within limits.max_file_size_mb —
  binary and oversized files are never touched. PackageResult gains a
  redacted field.
- cli.py: passes limits.redact_secrets into create_zip(), prints a
  one-line redaction summary, forwards redacted entries to the report.
- cli_display.py: print_redaction_summary() — same 'surface it, don't
  hide it' treatment as large-file warnings, silent when nothing was
  redacted.
- report.py: itemizes every redacted file + which pattern matched.
- project_config.py: also touches the workspace-gitignore docstrings
  as part of the same pass — see the next commit for the rest of that
  change (config.py, webui/persist.py), which landed separately
  because those files have no redaction-related content.
2026-09-03 01:33:22 +05:30
Deepesh KumarandGitHub cc907cf4d4 Update README.md 2026-08-31 02:01:31 +05:30
akadeepesh 74529836d9 docs: add changelog for 0.4.1 v0.4.1 2026-08-30 23:28:59 +05:30
akadeepesh 3e4773c2d5 feat: automatic workspace cleanup and secret-redaction config
- New cleanup.py: after every successful command, prunes
  .contextzip/output/<mode>/ zip sets, backups/, and inbox/applied/
  down to the most recent cleanup.keep_recent (default 1) — no
  confirmation, no separate command. Deliberately brutal rather than
  cautious, since every zip is trivially reproducible.
- New redact.py: curated high-precision patterns (AWS/Google/GitHub/
  Slack/Stripe/Anthropic/OpenAI keys, JWTs, private-key blocks, and a
  conservative generic key/secret/token/password assignment pattern)
  with placeholder-value filtering.
- project_config.py: new CleanupConfig (enabled, keep_recent); updated
  the redact_secrets docstring to describe actual enforced behavior
  instead of 'reserved for a future...not yet enforced.
2026-08-30 23:25:25 +05:30
akadeepesh 7f7954ad1f chore(release): bump version to 0.4.1 and update changelog 2026-08-30 23:24:06 +05:30
akadeepesh 0ba6b1f121 feat(cli): wire per-mode output, auto-cleanup, and redaction into the run
- Main run, apply-zip, watch, and config converted from Panel-based
  messaging to ok/warn/err/info.
- Wire write_scan_report()/write_apply_report() into the main
  packaging flow and apply-zip; print a dim 'Full report: ...' line.
- Compute run mode (standard/git-changes/prompt) once and pass it
  through to create_zip() and the report, replacing the old
  git_changes boolean.
- Pass limits.redact_secrets into create_zip() and print a one-line
  redaction summary when anything was caught.
- Auto-run .contextzip/ cleanup after every successful command
  (main run and apply-zip) per the new cleanup.* project settings.
- Drop the '.gitignore patterns applied' line entirely (dead weight,
  no signal) and remove the now-unused used_gitignore variable.
- Clipboard step no longer wraps in a status spinner; folder-opened
  no longer prints anything.
2026-08-30 23:24:06 +05:30