diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..f512001 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,91 @@ +name: Bug report +description: Something isn't working correctly +title: "fix: " +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to report a bug. Please fill out the sections below so we can reproduce and fix it quickly. + + - type: input + id: version + attributes: + label: contextzip version + description: Run `contextzip --version` and paste the output + placeholder: "contextzip, version 0.1.1" + validations: + required: true + + - type: dropdown + id: os + attributes: + label: Operating system + options: + - Windows + - macOS + - Linux + validations: + required: true + + - type: input + id: python + attributes: + label: Python version + description: Run `python --version` and paste the output + placeholder: "Python 3.12.0" + validations: + required: true + + - type: dropdown + id: framework + attributes: + label: Project type (what was contextzip run against?) + options: + - Node.js + - Next.js + - Python + - Django + - FastAPI + - Rust + - Go + - Ruby + - Unknown / not detected + - Other + validations: + required: false + + - type: textarea + id: description + attributes: + label: What happened? + description: A clear description of the bug + validations: + required: true + + - type: textarea + id: reproduction + attributes: + label: Steps to reproduce + placeholder: | + 1. Run `contextzip --dry-run` in a Next.js project + 2. Notice that `src/` is excluded even though it shouldn't be + 3. ... + validations: + required: true + + - type: textarea + id: expected + attributes: + label: What did you expect to happen? + validations: + required: true + + - type: textarea + id: output + attributes: + label: Terminal output + description: Paste the full terminal output here (use `contextzip --verbose` for more detail) + render: shell + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..b346593 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,52 @@ +name: Feature request +description: Suggest a new framework, flag, or behaviour +title: "add: " +labels: ["enhancement"] +body: + - type: markdown + attributes: + value: | + Have an idea? The most useful contributions are new framework rule sets — if your stack isn't well-supported, tell us what files it produces and what should be excluded. + + - type: dropdown + id: type + attributes: + label: What kind of feature is this? + options: + - New framework / language support + - New CLI flag or option + - Clipboard / platform improvement + - Output / display improvement + - Other + validations: + required: true + + - type: textarea + id: problem + attributes: + label: What problem does this solve? + description: Describe the workflow pain point this would fix + placeholder: "When I run contextzip on an Elixir project, it includes the _build/ directory which is huge and useless for AI context..." + validations: + required: true + + - type: textarea + id: solution + attributes: + label: Proposed solution + description: What would you like to see? + validations: + required: true + + - type: textarea + id: framework_details + attributes: + label: If this is a new framework — what should be excluded? + description: List the directories and files that are auto-generated and should never be in an AI context package + placeholder: | + _build/ + deps/ + .elixir_ls/ + mix.lock + validations: + required: false diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..941130b --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,33 @@ +## What does this PR do? + + + +## Type of change + +- [ ] Bug fix +- [ ] New framework / language rule set +- [ ] New feature (flag, behaviour) +- [ ] Documentation update +- [ ] Chore (deps, tooling, refactor) + +## Testing + + + +- [ ] Ran `contextzip --dry-run --verbose` on a real project +- [ ] Tested on the affected platform (Windows / macOS / Linux) +- [ ] If adding a new framework: tested against a real project of that type + +## If adding a new framework rule set + +- [ ] Created `contextzip/rules/yourlang.py` with a `PATTERNS` list +- [ ] Registered it in `filters.py` under `_RULE_REGISTRY` +- [ ] Added detection logic in `detector.py` +- [ ] Verified detection fires correctly (`contextzip --dry-run` shows the framework name) +- [ ] Verified the right directories are excluded + +## Checklist + +- [ ] My changes follow the existing code style +- [ ] I've added docstrings to any new public functions +- [ ] I've updated `CHANGELOG.md` under an `[Unreleased]` section diff --git a/.gitignore b/.gitignore index 8422f6f..5c8e9fa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,37 @@ +# Python +__pycache__/ +*.pyc +*.pyo +*.pyd +*.egg-info/ +*.egg +.eggs/ +dist/ +build/ .venv/ -contextzip.egg-info/ -contextzip/__pycache__/ -contextzip/rules/ -dist/ \ No newline at end of file +venv/ +env/ +.Python +pip-wheel-metadata/ + +# Testing +.pytest_cache/ +.mypy_cache/ +.ruff_cache/ +.coverage +htmlcov/ +coverage.xml + +# IDE +.vscode/ +.idea/ +*.swp +*.swo + +# OS +.DS_Store +Thumbs.db +desktop.ini + +# contextzip output files (don't commit test zips) +*_context_*.zip diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..db1d1f0 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,33 @@ +# Changelog + +All notable changes to contextzip are documented here. + +The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +This project uses [Semantic Versioning](https://semver.org/). + +--- + +## [0.1.1] — 2026-05-15 + +### Fixed +- LICENSE link in README now points to GitHub instead of a relative path that broke on PyPI +- License metadata updated to SPDX string format (`"MIT"`) to comply with setuptools ≥ 77 + +--- + +## [0.1.2] — 2026-05-15 + +### Added +- Smart framework and language detection (Next.js, Node.js, Python, Django, FastAPI, Rust, Go, Ruby) +- Automatic exclusion rules per detected ecosystem +- `.gitignore` patterns respected automatically (`--no-gitignore` to bypass) +- `--include` flag for scoping to specific directories (exact path-boundary matching) +- `--exclude` flag for additional gitignore-style exclusion patterns +- `--dry-run` flag to preview without creating any files +- `--verbose` flag showing every file with its size +- `--output` flag for custom ZIP destination +- `--no-clipboard` flag to skip clipboard/folder-open step +- Tiered clipboard strategy: file-on-clipboard (macOS/Linux), Explorer with file selected (Windows), path fallback +- Warnings for large files (≥ 1 MB), binary files, and skipped files (dangling symlinks, permission errors) +- Rich terminal output with panels, progress bars, and colour-coded detection results +- Compression stats (ratio, size before/after) shown after ZIP creation diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..3ef7aad --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,109 @@ +# Contributing to contextzip + +Thanks for taking the time to contribute. This document covers how to get set up, what kinds of contributions are most useful, and how to submit them. + +--- + +## What we're looking for + +- **New framework rule sets** — if your stack isn't detected or the exclusions aren't right, a new `rules/` file is the most useful contribution +- **Bug fixes** — especially edge cases around symlinks, path handling, and platform-specific clipboard behaviour +- **Platform improvements** — clipboard integration on Linux/Windows can always be improved +- **Documentation fixes** — typos, unclear instructions, outdated examples + +Please **open an issue before starting a large PR** so we can discuss the approach first. Small fixes (typos, obvious bugs) can go straight to a PR. + +--- + +## Setting up locally + +```bash +git clone https://github.com/akadeepesh/contextzip +cd contextzip + +python -m venv .venv + +# Windows +.venv\Scripts\activate +# macOS / Linux +source .venv/bin/activate + +pip install -e . +``` + +Verify it works: + +```bash +contextzip --version +contextzip --dry-run # run from any project directory +``` + +--- + +## Adding a new framework + +1. Create `contextzip/rules/yourlang.py`: + +```python +""" +YourLang exclusion rules. +""" + +PATTERNS = [ + "build/", + "*.compiled", + ".cache/", +] +``` + +2. Register it in `contextzip/filters.py` under `_RULE_REGISTRY`: + +```python +_RULE_REGISTRY: dict[str, str] = { + ... + "yourlang": "contextzip.rules.yourlang", +} +``` + +3. Add a detection rule in `contextzip/detector.py`: + +```python +_Rule( + name="YourLang", + module="yourlang", + check=lambda p: _file_exists(p, "yourlang.config"), + weight=3, +), +``` + +4. Test it: + +```bash +mkdir /tmp/test-yourlang && touch /tmp/test-yourlang/yourlang.config +cd /tmp/test-yourlang && contextzip --dry-run --verbose +``` + +--- + +## Submitting a PR + +1. Fork the repo and create a branch: `git checkout -b fix/your-description` +2. Make your changes +3. Test manually — run `contextzip --dry-run --verbose` on a real project +4. Commit with a clear message: `git commit -m "add: Elixir/Mix rule set"` +5. Push and open a PR against `main` + +PR titles should follow the format: +- `add: ` — new feature or rule set +- `fix: ` — bug fix +- `docs: ` — documentation only +- `chore: ` — maintenance, deps, tooling + +--- + +## Code style + +- Follow the existing patterns in the codebase — each module has a clear single responsibility +- Type hints on all public functions +- Docstrings on all modules and public functions +- Keep rule files simple — just a `PATTERNS` list with comments explaining non-obvious exclusions diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..2ce57e9 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,32 @@ +# Security Policy + +## Supported Versions + +| Version | Supported | +| ------- | --------- | +| 0.1.x | ✅ | + +Older versions will not receive security patches. Always use the latest release. + +## Reporting a Vulnerability + +**Please do not report security vulnerabilities through public GitHub issues.** + +If you discover a security vulnerability, email **akadeepesh@gmail.com** with: + +- A description of the vulnerability +- Steps to reproduce it +- The potential impact +- Any suggested fix (optional) + +You can expect an acknowledgement within **48 hours** and a full response within **7 days**. + +If the vulnerability is confirmed, a patch will be released as soon as possible and you will be credited in the release notes (unless you prefer to remain anonymous). + +## Scope + +contextzip is a local CLI tool that reads your filesystem and creates ZIP archives. It does not make network requests, collect data, or transmit anything anywhere. The primary security considerations are: + +- **Path traversal** — ensuring files outside the project directory are not included +- **Symlink handling** — dangling or malicious symlinks are skipped, not followed blindly +- **Secrets in archives** — `.env` and key files are excluded by default, but users should always run `--dry-run` before sharing archives containing sensitive projects