From d8faf3acf21a172b68fce11e89263b3d80117399 Mon Sep 17 00:00:00 2001 From: akadeepesh Date: Fri, 17 Jul 2026 08:10:35 +0530 Subject: [PATCH] chore: bump version to 0.4.0, add CHANGELOG entry and README section for eod/handoff --- CHANGELOG.md | 72 ++++++++++++++++++++++++++++++++++++++++++ README.md | 43 +++++++++++++++++++++++-- contextzip/__init__.py | 2 +- pyproject.toml | 2 +- 4 files changed, 115 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5fe7d3..de8cd7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -380,3 +380,75 @@ This project uses [Semantic Versioning](https://semver.org/). due to an incomplete `include` allowlist in `pyproject.toml` — replaced with auto-discovery so all current and future subpackages are captured automatically + +## [0.3.4] — 2026-06-21 + +### Added + +* `contextzip eod` — builds a paste-ready end-of-day prompt from today's + Claude/ChatGPT conversation plus whatever code changed, copied straight + to the clipboard. Does no summarizing itself — that's left to whichever + AI tool the prompt gets pasted into +* `contextzip handoff` — same pipeline, aimed at continuing a project in a + fresh chat after hitting a usage limit, rather than at an end-of-day report +* Per-branch commit checkpoints (`.contextzip/markers/eod.json`, + `.contextzip/markers/handoff.json`) so every run only reports what's new + since *that command* last ran on *that branch* — no manual bookkeeping, + no date-based guessing +* Three-case code-change resolution per file, checked in priority order: + 1. **Not pushed** — diff against the upstream branch (covers committed- + but-unpushed commits and uncommitted edits in one comparison) + the + complete current file + 2. **Diverged from Claude** — diff against the version Claude last + produced, matched by filename against a local artifacts folder + the + complete current codebase file + 3. **Since last run** — diff against the stored marker commit, or the + branch's merge-base with the default branch on a branch never tracked + before + the complete current file + + Brand-new untracked files skip the diff (no baseline exists) and are + included as full content only +* Best-effort fetching of Claude's artifact files for case 2, using the + user's own Claude.ai session key (`contextzip config --set-session-key`). + Explicitly degrades gracefully — a missing key, an expired cookie, or the + endpoint changing shape just skips case 2 with a warning, never fails the + whole `eod`/`handoff` run +* `contextzip config --set-session-key` / `--reset-session-key` — manage + the Claude session key alongside the existing Gemini key; default + `contextzip config` now shows both keys' status +* Text-clipboard support (`clipboard.handle_text()`) — `eod`/`handoff` + produce a prompt to paste, not a file to upload, so the existing + file-clipboard tiers gained a text-mode sibling (`pbcopy` / `xclip`+`xsel` + / `clip.exe`) +* `exports/` added to the base exclusion ruleset (next to `.contextzip/`) — + conversation exports and fetched Claude artifacts are contextzip's own + working files, never code to package or report on + +### Changed + +* `packager._ensure_gitignore()` generalised to accept an arbitrary entry + instead of being hardcoded to `.contextzip/`, so `exports/` can register + itself in `.gitignore` the same way on first use + +### Developer Notes + +* New modules: `markers.py` (per-branch checkpoint storage), `code_changes.py` + (the three-case decision tree), `claude_export.py` (locating the latest + export, inline-vs-attach sizing), `claude_artifacts.py` (best-effort + artifact fetching, rewritten on `httpx` for consistency with `ai/gemini.py` + rather than introducing a second HTTP stack), `brief.py` (orchestrates + `eod`/`handoff` end to end) +* `git.py` gained branch-aware primitives: `get_current_branch()`, + `get_default_branch()` (origin/HEAD detection with fallback chain), + `get_merge_base()`, `is_ancestor()`, `get_upstream_branch()`, + `diff_against()` (working-tree-aware — captures committed-since-baseline + and uncommitted changes in one diff), `changed_files_against()` +* A stored marker that's no longer an ancestor of `HEAD` (e.g. after a + rebase) is detected via `is_ancestor()` and silently recomputed from the + branch's merge-base, with a warning surfaced to the user rather than + producing a nonsense diff +* `claude_artifacts.py` matches Claude's flat artifact filenames against the + codebase by basename only, since artifacts carry no knowledge of the + repo's directory structure; ambiguous matches (same filename in multiple + directories) pick the most recently modified candidate and surface a + warning rather than guessing silently diff --git a/README.md b/README.md index 93e8bfc..94c16fc 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ contextzip eliminates that entirely. Run it from your project root — it detect - **Git-aware packaging** — use `--git-changes` to package only modified, staged, and untracked files; perfect for incremental debugging and PR review sessions - **AI-powered file selection** — describe your task in plain English with `--prompt` and Gemini selects the minimum relevant files automatically, no manual hunting required - **Terminal error watcher** — wrap any dev server with `contextzip watch` to auto-detect errors and package a ready-to-upload debug context in one keypress +- **End-of-day / handoff prompts** — `contextzip eod` and `contextzip handoff` turn a Claude/ChatGPT conversation export plus today's code changes into a paste-ready prompt, copied straight to your clipboard - **Persistent workspace** — all generated ZIPs land in `.contextzip/` at your project root, discoverable, reusable, and git-ignored automatically - **Warns before it's a problem** — flags large (≥ 1 MB) and binary files that AI tools can't read, before you waste an upload - **Handles edge cases** — dangling symlinks, unreadable files, and paths outside the project tree are caught and reported, never silently dropped @@ -88,7 +89,7 @@ contextzip [OPTIONS] | `--no-clipboard` | Skip the clipboard / folder-open step | | `--no-gitignore` | Ignore the project's `.gitignore` | -**Subcommands:** `exclude`, `include`, `watch`, `config` — run `contextzip --help` for full details. +**Subcommands:** `exclude`, `include`, `watch`, `config`, `eod`, `handoff` — run `contextzip --help` for full details. --- @@ -214,11 +215,49 @@ Press **D** and contextzip immediately writes `.contextzip/debug-context.zip`. Y --- +## End-of-day reports and chat handoffs + +If you work through a problem in a Claude or ChatGPT conversation and need to either (a) summarize what you did for an end-of-day report, or (b) continue the same work in a fresh chat after hitting a usage limit, `eod` and `handoff` build the prompt for you — contextzip does no summarizing itself; that's left to whichever AI tool you paste the result into. + +```bash +contextzip eod +contextzip handoff +``` + +**Setup:** export your conversation (any markdown export works) and drop the `.md` file into `exports/` at your project root. Both commands pick the most recently modified file there automatically. + +**What gets built:** + +- The conversation itself — pasted directly into the prompt if it's short, or referenced as an attachment if it's long enough that inlining it would burn through the next chat's context budget +- Whatever code changed, resolved per file in priority order: + 1. **Not pushed** — diffed against your upstream branch, plus the complete current file + 2. **Diverged from Claude** — diffed against the version Claude last produced (if you've set up a session key — see below), plus the complete current codebase file + 3. **Since last run** — diffed against a per-branch checkpoint that `eod`/`handoff` remember automatically, plus the complete current file +- New, untracked files are included as full content (there's nothing to diff them against) +- `eod` ends the prompt with a flat instruction to produce a work-log table; `handoff` frames it as continuing the project in a new chat + +The result is copied straight to your clipboard, and also saved to `.contextzip/` if you want to look it over first. + +**Optional — diffing against Claude's own version (case 2):** if you give contextzip your Claude.ai session key, `eod`/`handoff` will fetch the files Claude actually produced and compare them against your codebase, catching drift even after everything's pushed and in sync. + +```bash +contextzip config --set-session-key +``` + +This is best-effort by design — it depends on an undocumented Claude.ai endpoint, so a missing key, an expired cookie, or the endpoint changing shape just skips this check with a warning rather than failing the whole command. + +```bash +contextzip eod --dry-run # preview without advancing the checkpoint +contextzip handoff --no-fetch # skip the Claude-artifact fetch for this run +``` + +--- + ## What gets excluded contextzip stacks exclusion rules based on your detected stack, on top of your `.gitignore`. -**Always excluded:** `.git/`, `.env` files, logs, caches, editor config (`.vscode/`, `.idea/`), OS files (`.DS_Store`, `Thumbs.db`), and common binary formats. +**Always excluded:** `.git/`, `.env` files, logs, caches, editor config (`.vscode/`, `.idea/`), OS files (`.DS_Store`, `Thumbs.db`), common binary formats, and contextzip's own `.contextzip/` and `exports/` working folders. **By framework:** diff --git a/contextzip/__init__.py b/contextzip/__init__.py index f6f5047..9f2e32e 100644 --- a/contextzip/__init__.py +++ b/contextzip/__init__.py @@ -1,6 +1,6 @@ """contextzip — intelligent codebase packager for AI tools.""" -__version__ = "0.3.3" +__version__ = "0.3.4" from contextzip.api import ( FileCollection, diff --git a/pyproject.toml b/pyproject.toml index e3f92d5..dc5e37e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "contextzip" -version = "0.3.3" +version = "0.3.4" description = "Intelligently package your codebase for AI tools" readme = "README.md" requires-python = ">=3.9"