{"id":37079177,"url":"https://github.com/jaimemartinagui/gvit","last_synced_at":"2026-01-14T09:35:07.366Z","repository":{"id":320284306,"uuid":"1077751956","full_name":"jaimemartinagui/gvit","owner":"jaimemartinagui","description":null,"archived":false,"fork":false,"pushed_at":"2025-11-17T21:46:25.000Z","size":2460,"stargazers_count":14,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-11-17T22:03:06.275Z","etag":null,"topics":["cli","conda","python","virtual-environment"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jaimemartinagui.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-16T17:27:52.000Z","updated_at":"2025-11-17T21:46:29.000Z","dependencies_parsed_at":null,"dependency_job_id":"5e7b6f6f-a0ce-461b-bdd6-22f08d2914e2","html_url":"https://github.com/jaimemartinagui/gvit","commit_stats":null,"previous_names":["jaimemartinagui/gvit"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/jaimemartinagui/gvit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaimemartinagui%2Fgvit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaimemartinagui%2Fgvit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaimemartinagui%2Fgvit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaimemartinagui%2Fgvit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jaimemartinagui","download_url":"https://codeload.github.com/jaimemartinagui/gvit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaimemartinagui%2Fgvit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28416119,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T08:38:59.149Z","status":"ssl_error","status_checked_at":"2026-01-14T08:38:43.588Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","conda","python","virtual-environment"],"created_at":"2026-01-14T09:35:06.531Z","updated_at":"2026-01-14T09:35:07.358Z","avatar_url":"https://github.com/jaimemartinagui.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n```\n                      ░██   ░██    \n                            ░██    \n ░████████ ░██    ░██ ░██░████████ \n░██    ░██ ░██    ░██ ░██   ░██    \n░██    ░██  ░██  ░██  ░██   ░██    \n░██   ░███   ░██░██   ░██   ░██    \n ░█████░██    ░███    ░██    ░████ \n       ░██                         \n ░███████                          \n\n\nGit-aware Virtual Environment Manager\n```\n\n**Automates virtual environment management for Git repositories.**\n\n\u003cdiv\u003e\n\n[![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)\n[![PyPI version](https://img.shields.io/pypi/v/gvit.svg)](https://pypi.org/project/gvit/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Tests](https://img.shields.io/badge/tests-49%20passing-brightgreen.svg)](#-testing)\n[![Coverage](https://img.shields.io/badge/coverage-33%25-orange.svg)](#-testing)\n\n\u003c/div\u003e\n\n---\n\n## 📋 Table of Contents\n\n- ⭐ [Vision](#-vision)\n- 🚀 [Motivation](#-motivation)\n- ☑️ [What gvit does](#️-what-gvit-does)\n- 💻 [Installation](#-installation)\n- 🧩 [Usage](#-usage)\n  - [Initial Configuration](#initial-configuration)\n  - [Package Manager \u0026 Virtual Environment Backend](#package-manager--virtual-environment-backend)\n  - [Clone a Repository](#clone-a-repository)\n  - [Initialize a New Project](#initialize-a-new-project)\n  - [Setup an Existing Repository](#setup-an-existing-repository)\n  - [Pull Changes](#pull-changes-and-update-dependencies)\n  - [Commit with Validation](#commit-with-dependency-validation)\n  - [Check Status](#check-status)\n  - [Configuration Management](#configuration-management)\n  - [Environment Management](#environment-management)\n  - [Logs Management](#logs-management)\n  - [Git Commands](#use-git-commands-directly)\n  - [Explore Commands](#explore-commands)\n- 🧠 [How it works](#-how-it-works)\n- ⚙️ [Configuration](#️-configuration)\n- 🧱 [Architecture](#-architecture)\n- 🧭 [Roadmap](#-roadmap)\n- 🧪 [Testing](#-testing)\n- 🤝 [Contributing](#-contributing)\n- ⚖️ [License](#️-license)\n\n---\n\n## ⭐ Vision\n\n\u003e *“One repo, its own environment — without thinking about it.”*\n\nThe goal of **`gvit`** CLI is to eliminate the need to manually create or update virtual environments. No more friction between version control and Python environment management. Git and Python should work together seamlessly — this tool makes it possible.\n\n---\n\n## 🚀 Motivation\n\nHave you ever cloned a project and had to do all this?\n\n```bash\ngit clone https://github.com/someone/project.git\ncd project\npython -m venv .venv\nsource .venv/bin/activate\npip install -r requirements.txt\n```\n\nWith **`gvit`**, all of that happens automatically:\n\n```bash\n# Clone from scratch\ngvit clone https://github.com/someone/project.git\n\n# Or setup an existing repo\ncd existing-project\ngvit setup\n```\n\n🎉 Environment created and dependencies installed!\n\n---\n\n## ☑️ What `gvit` does\n\n* 🪄 **Automatically creates environments** when cloning or initializing repos.\n* 🐍 **Multiple backends**: `venv` (built-in), `conda`, `virtualenv` and `uv` support.\n* 📦 Choose your **package manager** to install dependencies (`uv` or `pip`).\n* 🔄 **Auto-syncs environment on pull** if there are any changes in the dependencies.\n* ⬇︎ **Installs dependencies** from `requirements.txt`, `pyproject.toml`, or custom paths. **Supports extra dependencies** (dev, test, etc.).\n* 🔒 **Dependency validation**: `commit` command validates installed packages match declared dependencies.\n* 📄 **Status overview**: `status` command shows both Git and environment changes in one view.\n* 🍁 **Git command fallback**: Use `gvit` for all git commands - unknown commands automatically fallback to git.\n* 📝 **Tracks environments** in registry (`~/.config/gvit/envs/`) with metadata and dependency hashes.\n* 👉 **Interactive** environment management.\n* 🧘 **Cleans orphaned environments** automatically with `prune` command.\n* 📊 **Command logging**: Automatic tracking of all command executions with analytics and error capture.\n* 🧠 **Remembers your preferences** via local configuration (`~/.config/gvit/config.toml`).\n* 🔧 **Flexible configuration**: per-repository (`.gvit.toml`) or global settings.\n* 🌳 **Visual command tree** to explore available commands.\n\n---\n\n## 💻 Installation\n\n⚠️ **Important:** Install `gvit` **globally**, not in a project-specific virtual environment. Since `gvit` manages virtual environments, it needs to be available system-wide.\n\n### Recommended: pipx (isolated global install)\n\n```bash\n# Install pipx if you don't have it\npython3 -m pip install --user pipx\npython3 -m pipx ensurepath\n\n# Install gvit with pipx\npipx install gvit\n```\n\n**Why pipx?**\n- ✅ Installs CLI tools in isolated environments\n- ✅ Makes them globally available\n- ✅ Prevents dependency conflicts\n- ✅ Easy to upgrade and uninstall\n\n### Alternative: pip (global install)\n\n```bash\n# Install globally (may require sudo on some systems)\npip install gvit\n\n# Or with --user flag\npip install --user gvit\n```\n\n### Verify Installation\n\n```bash\ngvit --version\n\n# Should work from any directory\ncd ~ \u0026\u0026 gvit --version\n```\n\n---\n\n## 🧩 Usage\n\n### Initial Configuration\n\nSet up your default preferences (interactive):\n\n```bash\ngvit config setup\n```\n\nOr specify options directly:\n\n```bash\n# Use venv with uv\ngvit config setup --backend venv --package-manager uv --python 3.11 --base-deps requirements.txt\n\n# Or use conda with pip\ngvit config setup --backend conda --package-manager pip --python 3.12\n\n# Or use conda with uv\ngvit config setup --backend conda --package-manager uv --python 3.11\n\n# Or use virtualenv with pip\ngvit config setup --backend virtualenv --package-manager pip --python 3.11\n\n# Or use uv with uv\ngvit config setup --backend uv --package-manager uv --python 3.11\n\n# Or any other combination...\n```\n\n### Package Manager \u0026 Virtual Environment Backend\n\nThe **package manager** (`uv` or `pip`) and the **virtual environment backend** (`venv`, `virtualenv`, `conda` or `uv`) serve different purposes but complement each other.\n\nThe backend defines where the Python environment lives and how it is isolated — for example, whether packages are stored in a venv directory, a virtualenv, or a Conda environment.\n\nThe package manager defines how dependencies are installed and resolved inside that environment — for example, using `pip install` for the standard Python installer or `uv pip install` for a faster, cache-optimized installation.\n\nIn `gvit` users can freely combine both layers (e.g., uv with venv, or pip with conda), since the package manager operates independently of the environment backend as long as it can target the correct Python interpreter.\n\n### Clone a Repository\n\nBasic clone with automatic environment creation:\n\n```bash\ngvit clone https://github.com/user/repo.git\n```\n\n**Advanced options:**\n\n```bash\n# Custom environment name\ngvit clone https://github.com/user/repo.git --venv-name my-env\n\n# Specify Python version\ngvit clone https://github.com/user/repo.git --python 3.12\n\n# Install extra dependencies from pyproject.toml\ngvit clone https://github.com/user/repo.git --extra-deps dev,test\n\n# Skip dependency installation\ngvit clone https://github.com/user/repo.git --no-deps\n\n# Force overwrite existing environment\ngvit clone https://github.com/user/repo.git --force\n\n# Verbose output\ngvit clone https://github.com/user/repo.git --verbose\n```\n\n\u003cimg src=\"assets/img/clone.png\" alt=\"gvit clone example\" width=\"400\"\u003e\n\n### Initialize a New Project\n\nSimilar to `git init` but with environment setup:\n\n```bash\n# In current directory\ngvit init\n\n# In specific directory (--target-dir)\ngvit init -t my-project\n\n# With remote repository\ngvit init --remote-url https://github.com/user/my-project.git\n\n# With all options\ngvit init -t my-project \\\n  --remote-url https://github.com/user/my-project.git \\\n  --python 3.12 \\\n  --extra-deps dev,test\n```\n\n### Setup an Existing Repository\n\nIf you already have a cloned repository and want to set up the environment:\n\n```bash\n# In the repository directory\ncd my-existing-repo\ngvit setup\n\n# Or specify a different directory (--target-dir)\ngvit setup -t path/to/repo\n\n# With custom options\ngvit setup --python 3.12 --extra-deps dev,test\n\n# Skip dependency installation\ngvit setup --no-deps\n```\n\n### Pull Changes and Update Dependencies\n\nSmart `git pull` that automatically detects and reinstalls changed dependencies:\n\n```bash\n# Pull and auto-update dependencies if changed\ngvit pull\n\n# Pull without checking dependencies\ngvit pull --no-deps\n\n# Force reinstall all dependencies even if unchanged\ngvit pull --force-deps\n\n# Pass options to git pull\ngvit pull --rebase origin main\n```\n\n### Commit with Dependency Validation\n\nSmart `git commit` that validates your installed packages match your dependency files:\n\n```bash\n# Commit with automatic validation\ngvit commit -m \"Add new feature\"\n\n# Skip validation if needed\ngvit commit --skip-validation -m \"Quick fix\"\n\n# Pass any git commit options\ngvit commit -a -m \"Update everything\"\ngvit commit --amend\n```\n\n**What it validates:**\n- ✅ Detects added packages not declared in dependency files.\n- ✅ Detects removed packages still declared in dependency files.\n- ✅ Detects version changes not reflected in pinned versions.\n- ✅ Works with `requirements.txt`, `pyproject.toml`, and custom paths.\n- ✅ Shows detailed diff of package changes (added/removed/modified).\n\n### Check Status\n\nCombined view of Git status and environment changes:\n\n```\n# Show just repository (same as `git status`)\ngvit status\n\n# Show repository and environment status\ngvit status -e\n\n# In a specific directory\ngvit status -e --target-dir path/to/repo\n```\n\n**What it shows:**\n- 📂 **Repository Status**: Standard `git status` output.\n- 🐍 **Environment Status**: Packages added/removed/modified since last tracking.\n- ✅ Clean overview of both code and dependency changes.\n- ⚡ Quick way to see if you need to update dependency files.\n\n\u003cimg src=\"assets/img/status.png\" alt=\"gvit status example\" width=\"400\"\u003e\n\n### Configuration Management\n\n```bash\n# Add extra dependency groups to local config\ngvit config add-extra-deps dev requirements-dev.txt\ngvit config add-extra-deps test requirements-test.txt\n\n# Remove extra dependency groups\ngvit config remove-extra-deps dev\n\n# Show current configuration\ngvit config show\n```\n\n### Environment Management\n\n```bash\n# List all tracked environments\ngvit envs list\n\n# Show details of a specific environment\ngvit envs show my-env\n\n# Remove an environment (registry and backend)\ngvit envs delete my-env\n\n# Reset an environment (recreate and reinstall dependencies)\ngvit envs reset my-env\n\n# Reset without reinstalling dependencies\ngvit envs reset my-env --no-deps\n\n# Show activate command for current repository's environment\ngvit envs show-activate\n\n# Show activate command for a specific environment\ngvit envs show-activate --venv-name my-env\n\n# Show activate command with relative path (venv/virtualenv/uv only)\ngvit envs show-activate --relative\n\n# Activate environment directly (recommended)\neval \"$(gvit envs show-activate)\"\n\n# Show deactivate command for current repository's environment\ngvit envs show-deactivate\n\n# Show deactivate command for a specific environment\ngvit envs show-deactivate --venv-name my-env\n\n# Deactivate environment directly (recommended)\neval \"$(gvit envs show-deactivate)\"\n\n# Clean up orphaned environments (repos that no longer exist)\ngvit envs prune\n\n# Preview what would be removed\ngvit envs prune --dry-run\n\n# Auto-confirm removal\ngvit envs prune --yes\n```\n\n\u003cimg src=\"assets/img/prune.png\" alt=\"gvit prune example\" width=\"400\"\u003e\n\n\n**Interactive Environment Management**\n\n```bash\n# Open an interactive menu to manage your environments\ngvit envs manage\n```\n\n\u003cimg src=\"assets/gif/envs-manage.gif\" alt=\"gvit envs manage example\" width=\"600\"\u003e\n\n### Logs Management\n\n`gvit` automatically tracks all command executions for analytics and debugging:\n\n```bash\n# Show recent command logs\ngvit logs show\n\n# Limit number of entries\ngvit logs show --limit 10\n\n# Filter by environment\ngvit logs show --venv-name my-env\n\n# Show full commands\ngvit logs show --verbose\n\n# Show error messages\ngvit logs show --errors\n\n# Combine filters\ngvit logs show --limit 20 --venv-name my-env --errors --verbose\n\n# Show logs statistics\ngvit logs stats\n\n# Clear all logs\ngvit logs clear\n\n# Clear with auto-confirm\ngvit logs clear --yes\n\n# Enable/disable logging\ngvit logs enable\ngvit logs disable\n\n# Configure logging\ngvit logs config --show\ngvit logs config --max-entries 500\ngvit logs config --ignore \"status,tree\"\n```\n\n**What gets logged:**\n- ⏱️ **Timestamp**: When the command was executed.\n- 🎯 **Command**: Short command name (e.g., `status`, `envs.list`).\n- 🌍 **Environment**: Associated environment name (if applicable).\n- ⚡ **Duration**: Execution time in milliseconds.\n- ✅ **Status**: Success (✅) or failure (❌).\n- 📝 **Full Command**: Complete command with all arguments (verbose mode).\n- ❌ **Error**: Error message (if command failed).\n\n**Configuration:**\n- 🔧 Logs stored in `~/.config/gvit/logs/commands.csv`.\n- 🔢 Default max entries: 1000 (configurable).\n- 🚫 Ignored commands by default (configurable): read-only commands like `logs.show`, `envs.list`, `status`, `tree`.\n- 🎚️ Automatic log rotation when limit exceeded.\n\n\u003cimg src=\"assets/img/logs.png\" alt=\"gvit prune example\" width=\"500\"\u003e\n\n### Use Git Commands Directly\n\n`gvit` can replace `git` in your daily workflow! Any command not implemented in `gvit` automatically falls back to `git`:\n\n```bash\n# These work exactly like git commands\ngvit add file.py\ngvit diff --stat\ngvit log --oneline -10\ngvit branch -a\ngvit checkout -b feature\ngvit push origin main\ngvit stash\ngvit rebase main\n\n# Complete workflow with gvit\ngvit status              # gvit's enhanced status\ngvit add .\ngvit commit -m \"feat\"    # gvit's validated commit\ngvit push\n```\n\n**How it works:**\n- 🔍 `gvit` checks if the command is implemented (clone, commit, init, pull, status, etc.).\n- ✅ If implemented: runs `gvit`'s enhanced version.\n- 🔄 If not implemented: automatically forwards to `git`.\n- 🎯 Seamless experience - just replace `git` with `gvit`.\n\n**Git aliases support:**\n\n`gvit` automatically resolves your **git aliases** and uses `gvit`'s enhanced versions when available!\n\n```bash\n# If you have git aliases configured:\n# git config --global alias.st status\n# git config --global alias.ci commit\n# git config --global alias.co checkout\n\n# These will use gvit's enhanced versions\ngvit st -e   # → gvit status (with environment tracking)\ngvit ci -m   # → gvit commit (with validation)\n\n# This will use git directly\ngvit co main # → git checkout main\n```\n\n- 🔗 Respects all your existing git aliases.\n- 🚀 Automatically uses `gvit`'s enhanced versions when the alias resolves to a gvit command.\n- 🔄 Falls back to git for other commands.\n\n### Explore Commands\n\n```bash\n# Show all available commands in tree structure\ngvit tree\n\n# Output\ngvit\n├── clone\n├── commit\n├── config\n│   ├── add-extra-deps\n│   ├── remove-extra-deps\n│   ├── setup\n│   └── show\n├── envs\n│   ├── delete\n│   ├── list\n│   ├── manage\n│   ├── prune\n│   ├── reset\n│   ├── show\n│   ├── show-activate\n│   └── show-deactivate\n├── init\n├── logs\n│   ├── clear\n│   ├── config\n│   ├── disable\n│   ├── enable\n│   ├── show\n│   └── stats\n├── pull\n├── setup\n├── status\n└── tree\n```\n\n---\n\n## 🧠 How it works\n\n### Git related commands\n\n**`gvit clone`** → Clones repository + creates environment:\n1. **Clones the repository** using standard `git clone`.\n2. **Detects repository name** from URL (handles `.git` suffix correctly).\n3. Proceeds to environment setup.\n\n**`gvit init`** → Initializes Git repository + creates environment:\n1. **Initializes Git repository** using `git init`.\n2. **Optionally adds remote** if `--remote-url` is provided.\n3. Proceeds to environment setup.\n\n**`gvit setup`** → Creates environment for existing repository:\n1. **Verifies Git repository** exists in target directory.\n2. **Detects remote URL** if available.\n3. Proceeds to environment setup.\n\n**`gvit pull`** → Pulls changes and syncs dependencies:\n1. **Finds tracked environment** for current repository.\n2. **Runs `git pull`** with any extra arguments you provide.\n3. **Compares dependency file hashes** (stored in registry vs. current files).\n4. **Reinstalls only changed dependencies** automatically.\n5. **Updates registry** with new hashes.\n\n**`gvit commit`** → Validates dependencies before committing:\n1. **Finds tracked environment** for current repository.\n2. **Compares pip freeze outputs** (stored snapshot vs. current state).\n3. **Detects package changes**: added, removed, modified versions.\n4. **Validates dependency files** to ensure changes are reflected.\n5. **Shows detailed report** of discrepancies (if any).\n6. **Runs `git commit`** with any extra arguments you provide.\n\n**`gvit status`** → Shows combined repository and environment status:\n1. **Displays `git status` output** for repository changes.\n2. **Finds tracked environment** for current repository.\n3. **Compares pip freeze outputs** (stored snapshot vs. current state).\n4. **Shows package changes**: added, removed, modified versions.\n5. **Provides clean overview** of both code and dependency changes.\n\n### Environment Setup Process (common to all commands)\n\n1. **Creates virtual environment** using your preferred backend:\n   - **`venv`**: Python's built-in venv module (creates `.venv/`, or the defined environment name, in repo).\n   - **`virtualenv`**: Enhanced virtual environments (creates `.venv/`, or the defined environment name, in repo).\n   - **`conda`**: Conda environments (centralized management).\n   - **`uv`**: uv environments (an extremely fast Python package and project manager, written in Rust).\n2. **Resolves dependencies** with priority system:\n   - CLI arguments (highest priority).\n   - Repository config (`.gvit.toml`).\n   - Local config (`~/.config/gvit/config.toml`).\n   - Default values (lowest priority).\n3. **Installs dependencies** from:\n   - `pyproject.toml` (with optional extras support).\n   - `requirements.txt` or custom paths.\n   - Multiple dependency groups (_base, dev, test, etc.).\n4. **Tracks environment in registry**:\n   - Saves environment metadata to `~/.config/gvit/envs/{env_name}.toml`.\n   - Records dependency file hashes for change detection.\n   - Stores complete pip freeze snapshot for validation.\n   - Stores repository information (path, URL).\n5. **Validates and handles conflicts**: \n   - Detects existing environments.\n   - Offers options: rename, overwrite, or abort.\n   - Auto-generates unique names if needed.\n\n---\n\n## ⚙️ Configuration\n\n### Local Configuration\n\nGlobal preferences: `~/.config/gvit/config.toml`\n\n```toml\n[gvit]\nbackend = \"venv\"  # or \"conda\", \"virtualenv\", \"uv\"\npython = \"3.11\"\n\n[deps]\n_base = \"requirements.txt\"\ndev = \"requirements-dev.txt\"\ntest = \"requirements-test.txt\"\n\n[logging]\nenabled = true\nmax_entries = 1000  # Maximum log entries before rotation\nignored = [\"logs.show\", \"status\", \"tree\"]\n\n[backends.venv]\nname = \".venv\"  # Directory name for venv (default: .venv)\n\n[backends.virtualenv]\nname = \".venv\"  # Directory name for virtualenv (default: .venv)\n\n[backends.uv]\nname = \".venv\"  # Directory name for uv (default: .venv)\n\n[backends.conda]\npath = \"/path/to/conda\"  # Optional: custom conda path\n```\n\n### Environment Registry\n\nEnvironment tracking: `~/.config/gvit/envs/{env_name}.toml`\n\n```toml\n[environment]\nname = \"my-project\"\nbackend = \"conda\"\npath = \"/Users/user/miniconda3/envs/gvit\"\npython = \"3.11\"\ncreated_at = \"2025-01-22T20:53:01.123456\"\n\n[repository]\npath = \"/Users/user/projects/my-project\"\nurl = \"https://github.com/user/my-project.git\"\n\n[deps]\n_base = \"requirements.txt\"\ndev = \"requirements-dev.txt\"\n\n[deps.installed]\n_base_hash = \"a1b2c3d4e5f6g7h8\"  # SHA256 hash for change detection\ndev_hash = \"i9j0k1l2m3n4o5p6\"\n_freeze_hash = \"q7r8s9t0u1v2w3x4\"  # SHA256 hash of pip freeze output\n_freeze = \"\"\"  # Complete pip freeze snapshot for validation\npackage1==1.0.0\npackage2==2.3.4\n\"\"\"\ninstalled_at = \"2025-01-22T20:53:15.789012\"\n```\n\n### Repository Configuration\n\nPer-project settings: `.gvit.toml` (in repository root)\n\n```toml\n[gvit]\npython = \"3.12\"  # Override Python version for this project\n\n[deps]\n_base = \"requirements.txt\"\ndev = \"requirements-dev.txt\"\ninternal = \"requirements-internal.txt\"\n```\n\nOr use `pyproject.toml` (tool section):\n\n```toml\n[tool.gvit]\npython = \"3.12\"\n\n[tool.gvit.deps]\n_base = \"pyproject.toml\"\n```\n\n---\n\n## 🧱 Architecture\n\n### Project Structure\n\n```\ngvit/\n├── src/gvit/                       # Source code\n│   ├── cli.py                      # CLI entry point \u0026 command routing\n│   ├── env_registry.py             # Environment registry management\n│   ├── git.py                      # Git operations \u0026 alias resolution\n│   ├── commands/                   # Command implementations\n│   │   ├── clone.py                # Clone repos with auto environment setup\n│   │   ├── init.py                 # Initialize new Git repos + environments\n│   │   ├── setup.py                # Setup environments for existing repos\n│   │   ├── pull.py                 # Smart pull with dependency sync\n│   │   ├── commit.py               # Commit with dependency validation\n│   │   ├── status.py               # Git + environment status overview\n│   │   ├── tree.py                 # Visual command structure explorer\n│   │   ├── config.py               # Configuration management\n│   │   └── envs.py                 # Environment management (list, delete, etc)\n│   ├── backends/                   # Backend implementations\n│   │   ├── common.py               # Shared backend functions\n│   │   ├── venv.py                 # Python's built-in venv\n│   │   ├── virtualenv.py           # virtualenv\n│   │   ├── uv.py                   # uv (faster, more features)\n│   │   └── conda.py                # conda environments\n│   └── utils/                      # Utilities \u0026 helpers\n│       ├── exceptions.py           # Custom exception classes\n│       ├── globals.py              # Constants and defaults\n│       ├── schemas.py              # Type definitions (TypedDict)\n│       ├── utils.py                # Helper functions\n│       └── validators.py           # Input validation\n├── tests/                          # Test suite (49 tests, 33% coverage)\n│   ├── unit/                       # Unit tests (38 tests)\n│   │   ├── test_env_registry.py\n│   │   ├── test_backends/\n│   │   └── test_utils/\n│   ├── integration/                # Integration tests (11 tests)\n│   │   └── test_envs.py\n│   ├── fixtures/                   # Test fixtures\n│   ├── conftest.py                 # Shared pytest fixtures\n│   └── README.md                   # Complete testing guide\n├── .coveragerc                     # Coverage configuration\n├── pytest.ini                      # Pytest configuration\n├── pyproject.toml                  # Project metadata \u0026 dependencies\n└── README.md                       # This file\n```\n\n### Key Components\n\n#### Core Modules\n\n- **`cli.py`** - Entry point with Typer app, command routing, and git fallback.\n- **`env_registry.py`** - Manages environment tracking in `~/.config/gvit/envs/`.\n- **`git.py`** - Git operations, alias resolution, and git command execution.\n\n#### Commands Layer\n\nEach command is self-contained with its own logic:\n\n#### Backends Layer\n\nAbstraction for different virtual environment tools.\n\n#### Utils Layer\n\nSupport utilities (configuration paths, defaults, constants, custom exceptions, etc.).\n\n### Data Flow\n\n```\n1. User runs command\n   ↓\n2. cli.py parses with Typer\n   ↓\n3. Command module executes logic\n   ↓\n4. Backend creates/manages environment\n   ↓\n5. env_registry.py tracks metadata\n   ↓\n6. Files saved to ~/.config/gvit/\n```\n\n### Configuration Hierarchy\n\n```\nCLI Arguments (highest priority)\n  ↓\nRepository Config (.gvit.toml or pyproject.toml)\n  ↓\nLocal Config (~/.config/gvit/config.toml)\n  ↓\nDefaults (globals.py)\n```\n\n---\n\n## 🧭 Roadmap\n\n### Current Release (v1.0.0)\n\n| Feature | Status | Description |\n|---------|--------|-------------|\n| **Clone command** | ✅ | Full repository cloning with environment setup |\n| **Init command** | ✅ | Initialize new Git repos with environment setup |\n| **Setup command** | ✅ | Create environment for existing repositories |\n| **Pull command** | ✅ | Smart git pull with automatic dependency sync |\n| **Commit command** | ✅ | Git commit with automatic dependency validation |\n| **Tree command** | ✅ | Visual command structure explorer |\n| **venv backend** | ✅ | Python's built-in venv support |\n| **conda backend** | ✅ | Complete conda integration |\n| **virtualenv backend** | ✅ | Complete virtualenv integration |\n| **uv backend** | ✅ | Complete uv integration |\n| **Config management** | ✅ | `setup`, `add-extra-deps`, `remove-extra-deps`, `show` |\n| **Environment registry** | ✅ | Track environments with metadata, dependency hashes, and freeze snapshots |\n| **Environment management** | ✅ | `list`, `show`, `delete`, `prune`, `reset`, `show-activate`, `show-deactivate` commands |\n| **Orphan cleanup** | ✅ | Automatic detection and removal of orphaned environments |\n| **Dependency resolution** | ✅ | Priority-based resolution (CLI \u003e repo \u003e local \u003e default) |\n| **pyproject.toml support** | ✅ | Install base + optional dependencies (extras) |\n| **Requirements.txt support** | ✅ | Standard pip requirements files |\n| **Custom dependency paths** | ✅ | Flexible path specification via config or CLI |\n| **Environment validation** | ✅ | Detect conflicts, offer resolution options |\n| **TypedDict schemas** | ✅ | Full type safety with typed configuration schemas |\n| **Dependency validation** | ✅ | Validate installed packages match declared dependencies on commit |\n| **Status command** | ✅ | Combined view of Git status and environment changes |\n| **Git command fallback** | ✅ | Automatic fallback to git for unknown commands |\n\n### Next Releases\n\n| Version | Status | Description |\n|---------|--------|-------------|\n| **0.6.0** | 📋 Planned | Add `checkout` command to switch branches and sync deps |\n| **0.6.0** | 📋 Planned | `gvit sync` command for full dependency refresh |\n| **1.0.0** | 🎯 Goal | Stable release with all core features |\n\n---\n\n## 🧪 Testing\n\n`gvit` has a comprehensive test suite with 49 tests and growing coverage.\n\nWhen testing CLI commands built with Typer (or Click), the test runner internally captures and redirects standard output (**stdout**). At the same time, pytest also captures stdout by default. This double capture can interfere with how Typer detects and writes to the terminal, causing missing or inconsistent output during tests. Running tests with the `-s` flag disables pytest’s output capture, allowing Typer’s console output (including echo and secho) to behave normally.\n\nIn short, use `pytest -s` to ensure CLI tests run with the same behavior as when executing the commands directly in a real terminal.\n\n```bash\n# Install test dependencies\npip install -e \".[test]\"\n\n# Run all tests\npytest -s\n\n# Run with coverage report\npytest -s --cov=src/gvit --cov-report=html\nopen tests/htmlcov/index.html\n```\n\n**Test Suite:**\n- ✅ 38 unit tests (fast, isolated)\n- ✅ 11 integration tests (end-to-end)\n- ✅ 33% coverage (target: 80%+)\n- ✅ Fully isolated (no system side effects)\n\n**Documentation:** See [tests/README.md](tests/README.md) for the complete testing guide including:\n- How to run and write tests.\n- Coverage analysis.\n- Available fixtures.\n- Best practices.\n\n---\n\n## 🤝 Contributing\n\nContributions are welcome! Areas we'd love help with:\n\n- Additional backends (pyenv, poetry).\n- `checkout` and other commands.\n- Cross-platform testing.\n- Documentation improvements.\n- **Writing tests** - See [tests/README.md](tests/README.md)\n\nOpen an issue or submit a pull request on [GitHub](https://github.com/jaimemartinagui/gvit).\n\n---\n\n## ⚖️ License\n\nMIT © 2025\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjaimemartinagui%2Fgvit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjaimemartinagui%2Fgvit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjaimemartinagui%2Fgvit/lists"}