117 Commits
Author SHA1 Message Date
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
akadeepesh b25406898c docs: document monorepo detection and workspace config; bump to 0.3.5
- README: expand framework detection section, new "Workspace
  location" section, drop stale exports/ mention left over from
  the eod/handoff removal
- Add CHANGELOG.md
- Bump version 0.3.4 -> 0.3.5 (pyproject.toml, __init__.py)
v0.3.5
2026-08-09 19:59:28 +05:30
akadeepesh f0b0f6779c feat(config): configurable .contextzip/ workspace location
Adds a precedence chain for where .contextzip/ is created:
env var (CONTEXTZIP_WORKSPACE_LOCATION) > project config
(.contextzip.json, git-committed, team-shared) > personal config
(per-machine, contextzip config --set-workspace) > default
(git-root, unchanged behavior).

Also fixes a latent bug this surfaced: .gitignore registration
derived git_root as workspace.parent, which only held true when
the workspace was always directly under git root. Now derives it
independently via _find_git_root and only registers .gitignore
when the workspace is actually inside the repo.

New: project_config.py (loads .contextzip.json), config.py
get/save/delete_workspace_location, cli.py --set-workspace/
--reset-workspace on `contextzip config`.
2026-08-09 19:59:01 +05:30
akadeepesh 9032a91ccf feat(detector): scan subdirectories for framework markers
Detection previously only checked project_dir itself, so a monorepo
like root/frontend/package.json + root/backend/requirements.txt
detected nothing and fell through to only the universal base
exclusion rules — leaving node_modules/, .venv/, etc. unexcluded
except by whatever .gitignore happened to catch.

Now scans project_dir plus a shallow, bounded subdirectory tree
(depth 2), skipping dependency/build dirs (node_modules, .venv,
.git, etc.) so it never walks into a large dependency tree. Runs
unconditionally, not just when root comes up empty, since a
root-level marker doesn't imply there's nothing else to find in
sibling directories.

DetectionResult now tracks which subdirectory each ecosystem was
found in (`sources`), surfaced in the CLI panel, e.g.
"Next.js (frontend/) + FastAPI (backend/)".
2026-08-09 19:58:46 +05:30
akadeepesh 64ff135102 Remove Claude.ai session key handling and related artifact fetching functionality 2026-08-09 04:15:04 +05:30
akadeepesh d8faf3acf2 chore: bump version to 0.4.0, add CHANGELOG entry and README section for eod/handoff v0.3.4 2026-07-17 08:10:35 +05:30
akadeepesh 5b54f95390 feat(cli): add eod and handoff subcommands, extend config with session key management 2026-07-17 08:10:21 +05:30
akadeepesh a140a3675d feat(cli_display,cli_onboard): add eod/handoff result panel and session key onboarding 2026-07-17 08:10:15 +05:30
akadeepesh 7a3580e396 feat(clipboard): add text-mode clipboard for eod/handoff prompts 2026-07-17 08:10:06 +05:30
akadeepesh 9e80971a1b refactor(packager,rules): generalise _ensure_gitignore and exclude exports/ from file scanning 2026-07-17 08:06:41 +05:30
akadeepesh 81e8ce3d6f feat(brief): add eod/handoff prompt orchestrator 2026-07-17 08:06:29 +05:30
akadeepesh 752f6261e2 feat(claude): add conversation export locator and artifact fetcher 2026-07-17 08:06:19 +05:30
akadeepesh 0126a909e8 feat(code_changes): add three-case file diff resolution for eod/handoff 2026-07-17 08:06:07 +05:30