# venvy 🐍

> **Auto-tracks `pip install` and `pip uninstall` in `requirements.txt` — like `package.json` for Python.**

Once set up, you just use pip normally. venvy silently keeps your `requirements.txt` in sync automatically.

---

## How it works

venvy injects a small hook (`venvy_hook.py`) into your venv's `site-packages`. This hook patches pip's internal `InstallCommand.run` and `UninstallCommand.run` — so every successful `pip install` or `pip uninstall` automatically updates `requirements.txt`. No wrappers, no aliases, no shell setup.

---

## Installation

```bash
pip install venvy        # global install recommended
# or
pipx install venvy
```

---

## Quick start

### 1. Create a venv (hook included automatically)

```bash
cd my-project
venvy create venv
```

Asks two questions:
```
  [1/2] Install ipykernel? [y/N]: n
  [2/2] Requirements file name [requirements.txt]:
```

Then: creates `.venv/`, upgrades pip, injects the tracking hook.

### 2. Activate your venv normally

```bash
# Windows CMD
.venv\Scripts\activate.bat

# Windows PowerShell
.venv\Scripts\Activate.ps1

# macOS / Linux
source .venv/bin/activate
```

### 3. Just use pip — requirements.txt updates automatically

```bash
pip install flask
# Output:
# Successfully installed flask-3.1.3 ...
# [venvy] + flask==3.1.3 → requirements.txt   ← automatic!

pip install requests httpx
# [venvy] + requests==2.31.0 → requirements.txt
# [venvy] + httpx==0.27.0 → requirements.txt

pip uninstall flask -y
# Successfully uninstalled flask-3.1.3
# [venvy] - flask → requirements.txt   ← automatic!
```

No extra commands. No wrappers. Just pip.

---

## Using an existing venv

If you already have a venv (not created by venvy):

```bash
source .venv/bin/activate      # activate it first (or don't — venvy finds it)
venvy install-hook             # inject the tracking hook
```

Or specify the path:
```bash
venvy install-hook .venv
venvy install-hook my_env
```

---

## All commands

```
venvy create venv              Create venv + inject pip hook
  --name -n      Venv directory name (default: .venv)
  --requirements -r  Requirements file name (prompted)
  --ipykernel    Install ipykernel for Jupyter
  --yes -y       Skip all prompts

venvy install-hook [path]      Inject hook into existing venv

venvy pip install <pkg>        Install + update requirements (manual fallback)
  --upgrade -U
venvy pip uninstall <pkg>      Uninstall + update requirements (manual fallback)
  --yes -y

venvy status                   Show venv info + hook status + requirements
venvy list                     List packages in requirements.txt
venvy sync                     Install all packages from requirements.txt

venvy --version
```

---

## Project structure

```
my-project/
├── .venv/
│   └── lib/pythonX.Y/site-packages/
│       ├── venvy_hook.py     ← the hook (auto-injected)
│       └── venvy_hook.pth    ← loads hook on every Python start
├── .venvy/
│   └── config.json           ← venvy project config
├── requirements.txt          ← auto-managed ✓
└── your_code.py
```

`.venvy/config.json`:
```json
{
  "venv_name": ".venv",
  "requirements_file": "requirements.txt",
  "install_ipykernel": false
}
```

---

## Restoring a project

```bash
git clone https://github.com/user/project
cd project
venvy create venv    # installs from existing requirements.txt automatically
# OR
python -m venv .venv
source .venv/bin/activate
venvy install-hook
venvy sync
```

---

## Comparison with npm

| npm | venvy |
|-----|-------|
| `npm init` | `venvy create venv` |
| `npm install pkg` | `pip install pkg` (auto-tracked after venvy setup) |
| `npm uninstall pkg` | `pip uninstall pkg` (auto-tracked) |
| `npm install` | `venvy sync` |
| `package.json` | `requirements.txt` |
| `node_modules/` | `.venv/` |

---

## License

MIT
