Commit Graph
129 Commits
Author SHA1 Message Date
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
akadeepesh 4f1fffd04d feat(packager): per-mode output folders + in-content secret redaction
- .contextzip/output/ now branches by run mode: output/codebase/,
  output/git-changes/, output/prompt/ (vibe.zip), output/watch/ —
  named after the flag that produced it, so it's unambiguous which
  zip is which without guessing.
- output_subdir_for_mode()/zip_filename_for_mode() are the single
  source of truth other modules (watcher.py, cleanup.py) build on.
- apply-zip's manifest auto-detection (find_latest_manifest) now
  searches recursively across the new per-mode subfolders instead of
  a flat glob.
- Implements limits.redact_secrets (previously persisted but never
  enforced, per the 0.4.0 changelog): text files already going into
  the archive get scanned for secret-shaped values and matched values
  are replaced with [REDACTED] before writing. Only ever scans files
  already known to be text and within max_file_size_mb, reusing the
  existing binary/large-file classification — never re-scans, never
  touches binaries or oversized files.
- Workspace-creation fallback warning converted from panel to a
  single warn()-style line.
2026-08-30 23:24:06 +05:30
akadeepesh b8c86674cc refactor(watch): minimal log output + bucket debug zip under output/watch/
- Convert 'Watching <command>' line, error prompts, exit summary, and
  the debug-context success/failure banner from panels to plain lines.
- debug-context.zip now writes to .contextzip/output/watch/ instead of
  the flat output/ folder, matching the same per-mode split applied to
  the main packaging command (see the packager.py commit).
2026-08-30 23:24:06 +05:30
akadeepesh afd0331a4e refactor(cli_display): replace boxed panels with a minimal log
- Introduce ok()/warn()/err()/info() as the four output primitives,
  replacing all rich.Panel/rich.Table usage.
- Merge the old 'Scanned N files' + 'Packed N files' steps into one
  print_scan_and_pack() line.
- Drop the contextzip vX.X.X / project-path banner from every command.
- Full file listings and exclusion breakdowns move to the report file
  (report.py) and behind -v/--verbose; the terminal shows one line
  per step.
- Add print_auto_cleanup() and print_redaction_summary() for the two
  newer background steps (workspace cleanup, secret redaction).
2026-08-30 23:24:06 +05:30
akadeepesh db597e04c2 refactor: improve workspace creation error message 2026-08-30 01:43:02 +05:30
akadeepesh ab3aa5105c refactor: simplify config UI server output 2026-08-30 01:42:03 +05:30
akadeepesh fb89c435f0 refactor: simplify watch mode output 2026-08-30 01:41:57 +05:30
akadeepesh 10f2f7b512 refactor: simplify AI and onboarding output 2026-08-30 01:41:49 +05:30
akadeepesh a311e68386 refactor: streamline CLI command output 2026-08-30 01:41:24 +05:30
akadeepesh 46e7aeabc2 refactor: simplify CLI terminal output 2026-08-30 01:41:07 +05:30
akadeepesh 1c8e815658 feat: add packaging reports for detailed output 2026-08-30 01:40:58 +05:30
akadeepesh ae94603520 ci: improve PyPI release validation 2026-08-30 01:40:45 +05:30
akadeepesh 35f7fb6ad8 fix: bump pyproject.toml to 0.4.0 v0.4.0 2026-08-26 21:35:24 +05:30
akadeepesh aaf0ed87dd chore(release): 0.4.0
Document the new config schema, the redesigned config UI, and the
known limitation that limits.redact_secrets is persisted but not yet
enforced.
2026-08-26 16:16:56 +05:30
akadeepesh 9869f4c96f refactor(README): streamline contextzip explanation and enhance feature descriptions 2026-08-26 16:16:53 +05:30
akadeepesh d2a4728ae1 feat(webui): redesign the config UI with tabs and a diff-based tree
Replace the single always_include/always_exclude pane with five tabs:
Files, AI selection, Workspace, Advanced, and a live Raw JSON preview.
The file tree and pattern list now render as a diff — a solid gutter
and +/- marks on every row — instead of checkboxes, matching the
git-diff mental model the rest of the tool already uses.

Still a single dependency-free HTML string: no build step, no Node.js,
no network calls from the page itself. Typography uses each OS's own
system font stack rather than a bundled or CDN-fetched face, to keep
that property.

Pattern-list and tree updates are now applied optimistically on every
edit instead of waiting on the debounced /api/preview round-trip.
2026-08-26 14:44:30 +05:30
akadeepesh 410d51e6bd feat(webui): expose and persist the full project config
/api/state now returns workspace_location, scan_depth, ai, limits,
applied_zip_retention, and webui alongside the file tree — previously
only always_include/always_exclude. /api/save accepts and validates
the same full shape. save_config_from_ui() merges nested objects
(ai/limits/webui) key-by-key rather than replacing them wholesale, so
a partial save can't wipe fields it doesn't know about.

launch_config_ui() now honors webui.port (falling back to a random
port if the configured one is taken) and webui.auto_open (skips
launching a browser tab when off).
2026-08-26 14:44:25 +05:30
akadeepesh b4b787fe50 feat(apply-zip): make applied-zip retention configurable
_move_zip_to_applied() and execute_plan() take a retain count instead
of always keeping only 1. cmd_apply_zip now loads the project config
and passes applied_zip_retention through, defaulting to 1 to match
prior behavior.
2026-08-26 14:44:19 +05:30
akadeepesh 2dedeb48dc feat(ai): support a project-level prompt template
ai.prompt_template is now prepended to every generated prompt.txt,
ahead of the task description, as a 'Project conventions:' block.
Threaded through ai_select()/build_prompt_only_txt() in selector.py,
run_ai_selection() in cli_ai.py, and the --prompt call site in cli.py.
2026-08-26 14:44:13 +05:30
akadeepesh e65e7b19c7 feat(filters): make the large-file threshold configurable
resolve_files() and resolve_files_from_git() now accept
large_file_warn_bytes instead of a fixed 1 MB constant. cli.py threads
a project's limits.max_file_size_mb through to both the filtering and
the warning text in output.
2026-08-26 14:44:08 +05:30
akadeepesh cb2110fde6 feat(config): extend project config schema
Add ai.prompt_template, a new LimitsConfig (max_file_size_mb,
redact_secrets), a new WebUIConfig (auto_open, port), and
applied_zip_retention. All new fields are optional with sensible
defaults and defensive parsing — a malformed value falls back to the
default rather than erroring. Foundation for the config UI redesign
and the features that follow in this release.
2026-08-26 14:44:03 +05:30
akadeepesh 3e23937ebc chore: remove .gitignore from .contextzip and add requirements.txt for project dependencies 2026-08-26 01:05:14 +05:30
akadeepesh 123a4e1f2d chore(release): document security hardening and bump to 0.3.9
Update README with the expanded secret-exclusion list and config file
permission note. Add CHANGELOG entry for 0.3.9.
2026-08-26 01:04:34 +05:30
akadeepesh beb995cbda chore: remove unused import, clarify .gitignore comment
Drop the unused GitChanges import in api.py. Expand the .gitignore
comment on .contextzip/ to note it's project-local and that the
Gemini API key is never stored there.
2026-08-26 01:04:31 +05:30
akadeepesh b9ae0a40c3 fix(apply-zip): handle wrapped zips and warn on structure mismatch
Detect when every entry in an AI-returned zip shares one incidental
top-level folder (the shape produced by 'zip -r' or GitHub's Download
ZIP) and strip it automatically when doing so clearly improves the
match against the project manifest, so files land at their real
project-relative paths.

Also warn before applying a zip whose paths barely match the project
at all, instead of silently treating every file as new. The
applied/ folder now keeps only the most recently applied zip.
2026-08-26 01:04:27 +05:30
akadeepesh ebd9c7cfc5 feat(rules): exclude SSH keys, cloud credentials, and Terraform state
Always-excluded patterns now cover SSH private keys, keystores
(.jks/.keystore/.p12/.pkcs12/.ppk), CLI credential files
(.npmrc/.netrc/.pypirc/.pgpass/.dockercfg), cloud provider credentials
(.aws/credentials, service-account JSON, kubeconfig), and Terraform
state files, which routinely hold plaintext secrets.
2026-08-26 01:04:23 +05:30
akadeepesh a3f9ba514f fix(config): chmod config file to 0600 on every write
Route all writes through a single _write_config() helper and re-apply
0600 permissions each time, not just on creation. A pre-existing file
from an older install (or one created under a permissive umask) could
otherwise stay group/world-readable indefinitely, exposing a plaintext
Gemini API key on shared machines.
2026-08-26 01:04:18 +05:30
akadeepesh 5ee834f792 fix(webui): use constant-time comparison for config UI auth token
Compare the request token with hmac.compare_digest instead of == to
close a timing side-channel on the local, single-use session token.
2026-08-26 01:04:14 +05:30
akadeepesh d9ca66d461 chore: bump version to 0.3.8 and update changelog for apply-zip feature v0.3.8 2026-08-24 09:01:04 +05:30
akadeepesh 4b1a306c77 docs: document apply-zip and the .contextzip/ workspace layout
Adds an 'Applying AI-returned changes' section covering the manifest
mechanism, the new/modified/unchanged/drifted/untracked classification
table, safety guarantees, and inbox/manifest resolution. Also updates
the command table, Python API table, and workspace layout diagram to
include inbox/, backups/, and the manifest sidecar.
2026-08-24 08:59:44 +05:30
akadeepesh ca14e0f6a0 feat(api): expose apply_zip() in the public API
Adds apply_zip() alongside get_files/get_git_changes/create_zip,
following the same plain-function, exception-raising style (no Click,
no Rich, no SystemExit). Exposes ApplyResult and ZipNotFoundError
from the package root.
2026-08-24 08:59:44 +05:30
akadeepesh 00dba7ac8c feat(cli): add 'contextzip apply-zip' command
Wires applier.py into the CLI: auto-detects a zip from
.contextzip/inbox/ (or takes an explicit path), prints a plan summary
(new/modified/unchanged/drifted/untracked counts), and only prompts
for confirmation when something looks risky — drift, untracked paths,
or no manifest at all. Clean modifications and new files apply with
no prompt.

Flags: --dry-run/-n, --verbose/-v, --yes/-y, --manifest.
2026-08-24 08:59:44 +05:30
akadeepesh c6871db8bd feat(applier): add apply-zip engine with local sidecar manifest
Introduces applier.py: resolves the AI-returned zip (inbox or explicit
path), diffs it against a per-zip manifest, and classifies every file
as new/modified/unchanged/drifted/untracked before writing anything.
Only ever adds or modifies files — no deletions are inferred.

packager.py now writes a <name>.manifest.json sidecar next to every
zip it creates, containing a hash of each included file. It's written
to disk only, never added as a zip entry, so it's never uploaded or
visible to whatever AI tool the zip is pasted into.

Safety: zip entries are validated against path traversal before
extraction; every file about to be overwritten is backed up under
.contextzip/backups/<timestamp>/ first; consumed zips are archived to
.contextzip/inbox/applied/ rather than deleted.
2026-08-24 08:59:43 +05:30
akadeepesh a840e7fbc0 feat: add visual config UI and first-run offer with enhanced exclusion suggestions v0.3.7 2026-08-24 02:09:30 +05:30
akadeepesh adda650263 chore: bump version to 0.3.7 2026-08-24 02:07:51 +05:30
akadeepesh ad18a39519 fix: update .gitignore to include config.json for version control 2026-08-24 02:07:48 +05:30
akadeepesh a0042ef837 docs: document the visual config UI 2026-08-24 02:06:43 +05:30
akadeepesh 5575a7899d feat(cli): wire up 'contextzip config --ui' and first-run offer
- 'contextzip config --ui' launches the local config UI directly
- First run in a project with no config at all offers to launch it
  interactively, gated on TTY + no CI env var + no --prompt/--output
- Declining is remembered per-machine (config.py) so it only asks once
- Accepting and saving mid-run reloads config and continues packaging
  immediately in the same invocation
2026-08-24 02:06:35 +05:30
akadeepesh 9d4bc08734 feat(webui): add local config UI frontend
Single-file HTML/CSS/JS, no build step, no CDN calls — colors and
typography matched to the showcase site's design tokens. Live file tree
with checkboxes, one-click exclude suggestions, working-config panel
with raw JSON preview, and a save flow with a success overlay.
2026-08-24 02:06:26 +05:30
akadeepesh a86855cd55 feat(webui): add local config UI server
Stdlib-only HTTP server bound to 127.0.0.1, with a random per-session
token (same approach as Jupyter Notebook) and no outbound network calls
of its own. Auto-shuts down on save, tab idle, or a hard time ceiling.

Includes:
- suggestions.py: detects PDFs, office docs, fonts, media, and anything
  over 1MB that isn't already covered by the default exclusion rules
- persist.py: writes always_include/always_exclude to
  .contextzip/config.json, reusing the existing workspace/.gitignore setup
2026-08-24 02:06:17 +05:30
akadeepesh 7b4e248862 feat(filters): add scan_all_files/classify_scanned_files for reusable tree scans
Splits file-tree scanning into a one-time disk walk (scan_all_files) plus
a pure in-memory classifier (classify_scanned_files) that can be run
against different include/exclude patterns without re-touching the
filesystem. resolve_files() is untouched — this is purely additive.

Prunes known-huge, always-irrelevant directories (.venv, node_modules,
.git, __pycache__, build output, etc.) during the walk itself, and
rejects symlinks that resolve outside the project tree (e.g. a venv's
bin/python pointing at the system interpreter).
2026-08-24 02:06:07 +05:30
akadeepesh 2bca7ceba9 bump version to 0.3.6 v0.3.6 2026-08-23 03:07:18 +05:30
akadeepesh 8dd3f48c8a feat: update workspace structure and improve gitignore handling 2026-08-23 03:03:34 +05:30
akadeepesh dc78feacf1 docs: document contextzip workspace and configuration 2026-08-23 03:03:10 +05:30
akadeepesh c828f50c02 feat: apply ai preferences to file selection 2026-08-23 03:03:02 +05:30
akadeepesh 587b6d2f4f feat: integrate project config into cli 2026-08-23 03:02:51 +05:30
akadeepesh 402266162b feat: organize contextzip output workspace 2026-08-23 03:02:38 +05:30
akadeepesh bcd89d2ac5 feat: apply project config to file selection 2026-08-23 03:02:31 +05:30
akadeepesh f0bbcf5a24 feat: add project-level contextzip configuration 2026-08-23 03:02:22 +05:30
akadeepesh 275fcb5387 feat: add cz as contextzip cli alias 2026-08-23 03:02:09 +05:30