PPM - Python Package Manager: Smart environment and package management CLI
Project description
PPM — Python Package Manager
██████╗ ██████╗ ███╗ ███╗
██╔══██╗██╔══██╗████╗ ████║
██████╔╝██████╔╝██╔████╔██║
██╔═══╝ ██╔═══╝ ██║╚██╔╝██║
██║ ██║ ██║ ╚═╝ ██║
╚═╝ ╚═╝ ╚═╝ ╚═╝
Smart Python environment and package management CLI
🎯 What is PPM?
PPM is a professional Python environment and package management CLI that wraps pip and venv with smart automation:
| Feature | Description |
|---|---|
| 🚀 venv automation | One-command environment init with OS detection |
| 🔄 requirements sync | Parse, validate, install, and lock dependencies |
| 🏗️ wheelhouse cache | Local .whl cache for offline and fast installs |
| 📡 fallback mirrors | Auto-retry with PyPI mirrors on network failure |
| 🔐 security audit | CVE scanning via pip-audit |
| 🔧 repair system | Detect and fix broken environments |
| 🔍 package search | Search PyPI with version and description display |
| 🩺 doctor checks | Full diagnostics on your setup |
⚡ Quick Start
Installation
The recommended way to install Python CLI tools globally is using pipx (which avoids externally-managed-environment errors on modern Linux):
# Install globally via pipx (Recommended)
pipx install rootx-ppm
# Or using pip in an isolated virtual environment
python3 -m venv .venv
source .venv/bin/activate
pip install rootx-ppm
If you are developing or want to install from source:
git clone https://github.com/Rootx202/PPM.git
cd PPM
pip install -e ".[dev]"
Or use the install script:
bash scripts/install.sh
First Run
# Initialize a virtual environment in your project
ppm init
# Sync requirements.txt
ppm sync
# Install a package
ppm install fastapi
# Run a security audit
ppm audit
# Check environment health
ppm doctor
📦 All Commands & Shortcuts
You can use either the full command or its shortcut (alias).
| Command | Shortcut | Description |
|---|---|---|
init |
i |
Initialize a new Python virtual environment. |
sync |
s |
Sync environment with requirements.txt. |
install |
in |
Install a package into the virtual environment. |
update |
up |
Update a package or all packages to latest versions. |
upgrade |
ug |
Upgrade the PPM tool itself to the latest version. |
remove |
rm |
Remove a package from the virtual environment. |
search |
se |
Search PyPI for packages matching a query. |
audit |
au |
Scan for vulnerabilities and deprecated packages. |
repair |
rp |
Repair a broken virtual environment. |
doctor |
doc |
Run full diagnostic checks on your environment. |
config |
cfg |
View or modify PPM configuration. |
wheelhouse build |
b |
Download wheels into the local cache. |
wheelhouse list |
ls |
List all cached wheels. |
wheelhouse stats |
st |
Show wheelhouse cache statistics. |
cache clean |
cl |
Clean the PPM wheelhouse cache. |
🛠️ Detailed Command Guide
ppm init (Alias: i) — Initialize Environment
ppm init # Create .venv in current directory
ppm init --force # Recreate existing venv
ppm init --name my-env # Custom venv name
Detects your OS and shows the correct activation command:
Linux/macOS: source .venv/bin/activate
Windows: .venv\Scripts\activate
ppm sync (Alias: s) — Sync Requirements
ppm sync # Sync with requirements.txt
ppm sync -r requirements/prod.txt # Use a specific file
ppm sync --offline # Use wheelhouse only
ppm sync --no-lock # Skip lock file generation
Generates ppm.lock.json with pinned versions after a successful sync.
ppm install (Alias: in) — Install Package
ppm install fastapi # Latest version
ppm install "fastapi>=0.100.0" # With version constraint
ppm install fastapi --version ">=0.100"
ppm install fastapi --offline # From wheelhouse only
Install strategy (in order):
- Check local wheelhouse cache
- Install from PyPI with configured mirrors
- Retry with exponential back-off
ppm update (Alias: up) — Update Package(s)
ppm update # Update ALL packages in requirements.txt
ppm update fastapi # Update a specific package to latest
ppm update -r requirements/dev.txt # Update from a specific file
This bypasses the local wheelhouse cache (unless already latest) and forcefully upgrades the requested packages.
ppm remove (Alias: rm) — Remove Package
ppm remove requests # With confirmation prompt
ppm remove requests -y # Skip confirmation
ppm search (Alias: se) — Search PyPI
ppm search fastapi # Search for packages
ppm search "http client" # Multi-word query
ppm search flask -n 5 # Limit to 5 results
Output:
┌─────────────────────────────────────────────────────┐
│ Search Results: 'fastapi' │
├─────────────┬──────────┬────────────────────────── │
│ Package │ Version │ Description │
├─────────────┼──────────┼────────────────────────── │
│ fastapi │ 0.110.0 │ FastAPI framework │
│ fastapi-cli │ 0.0.3 │ FastAPI CLI tool │
└─────────────┴──────────┴────────────────────────── │
ppm audit (Alias: au) — Security Audit
ppm audit # Audit installed packages
ppm audit -r requirements.txt # Audit a requirements file
ppm audit --fail # Exit 1 if vulnerabilities found
Output example:
⚠️ Found vulnerabilities:
┌─────────┬─────────┬───────────┬──────────┬────────────┐
│ Package │ Version │ ID │ Severity │ Fix │
├─────────┼─────────┼───────────┼──────────┼────────────┤
│ urllib3 │ 1.26.5 │ GHSA-xxx │ HIGH │ >= 2.0 │
└─────────┴─────────┴───────────┴──────────┴────────────┘
ppm repair (Alias: rp) — Repair Environment
ppm repair # Auto-repair
ppm repair -r requirements.txt -y # Repair and reinstall
Repair steps:
- Upgrade
pip,setuptools,wheel - Run
pip checkto detect conflicts - Force-reinstall conflicting packages
- Reinstall from requirements.txt (if provided)
- Purge pip cache
ppm doctor — Health Checks
ppm doctor
Checks:
- Python version >= 3.12
- pip available in PATH
- Virtual environment exists
- pip-audit installed
- Wheelhouse directory accessible
- Config file present
- Internet connectivity to pypi.org
ppm wheelhouse — Wheel Cache Management
ppm wheelhouse build # Download wheels from requirements.txt
ppm wheelhouse build -r requirements/prod.txt
ppm wheelhouse list # List cached wheels
ppm wheelhouse stats # Cache statistics
ppm cache — Cache Cleaning
ppm cache clean # Remove old wheel versions, keep latest
ppm cache clean --all # Remove ALL wheels
ppm cache clean -y # Skip confirmation
ppm config — Configuration
ppm config # Show current configuration
ppm config --set repository.timeout=60
ppm config --set offline_mode=true
⚙️ Configuration
PPM stores its configuration at:
| OS | Path |
|---|---|
| Linux | ~/.config/ppm/config.toml |
| macOS | ~/Library/Application Support/ppm/config.toml |
| Windows | %APPDATA%\ppm\ppm\config.toml |
Example config.toml
offline_mode = false
venv_name = ".venv"
[repository]
index_url = "https://pypi.org/simple"
mirrors = [
"https://pypi.tuna.tsinghua.edu.cn/simple",
"https://mirrors.aliyun.com/pypi/simple",
]
timeout = 30
max_retries = 3
trusted_hosts = []
[wheelhouse]
path = "~/.local/share/ppm/wheelhouse"
max_size_gb = 5.0
auto_clean = false
deduplicate = true
[logging]
level = "INFO"
Environment Variables
All settings can be overridden via environment variables:
| Variable | Description | Default |
|---|---|---|
PPM_INDEX_URL |
Primary PyPI index URL | https://pypi.org/simple |
PPM_FALLBACK_MIRRORS |
Comma-separated mirror URLs | Tsinghua, Aliyun |
PPM_WHEELHOUSE_DIR |
Wheelhouse directory path | ~/.local/share/ppm/wheelhouse |
PPM_LOG_LEVEL |
Log level (DEBUG/INFO/WARNING/ERROR) | INFO |
PPM_TIMEOUT |
HTTP request timeout (seconds) | 30 |
PPM_MAX_RETRIES |
Maximum retry attempts | 3 |
PPM_OFFLINE |
Enable offline mode (true/false) | false |
🏗️ Architecture
PPM follows Clean Architecture with clear separation of concerns:
ppm/
├── cli/ ← Typer CLI layer (user interface)
├── core/ ← Dependency injection container
├── services/ ← Business logic layer
│ ├── env_service.py
│ ├── install_service.py
│ ├── sync_service.py
│ ├── audit_service.py
│ ├── repair_service.py
│ ├── search_service.py
│ ├── doctor_service.py
│ └── wheelhouse_service.py
├── repositories/ ← PyPI access with fallback mirrors
├── environments/ ← venv creation and management
├── wheelhouse/ ← Local .whl cache management
├── installers/ ← Package installation logic
├── parsers/ ← requirements.txt parsing
├── security/ ← pip-audit vulnerability scanning
├── config/ ← TOML config management
├── models/ ← Domain models (dataclasses)
└── utils/ ← Console, logging, security utilities
Design Principles
- Clean Architecture: CLI → Services → Core → Infrastructure
- Dependency Injection:
ServiceContainerwires all components - Single Responsibility: Each module has one clear purpose
- No Shell Injection: All subprocesses use
shell=False - Async Where Useful: HTTP calls use
httpxwithasyncio
🧪 Testing
# Run all tests
pytest
# Run with coverage
pytest --cov=ppm --cov-report=html
# Run only unit tests (fast)
pytest tests/unit/ -v
# Run CLI tests
pytest tests/cli/ -v
# Skip slow integration tests
pytest -m "not slow"
🔐 Security
PPM takes security seriously:
- Package name validation: Rejects invalid/malicious names
- URL validation: Only
http://andhttps://allowed - No shell injection: All subprocess calls use
shell=False - Path traversal prevention: Safe path checks for wheelhouse
- Vulnerability scanning: Integrated
pip-auditCVE scanning
🛠️ Troubleshooting
ppm: command not found
pip install -e .
# Or ensure your Python scripts directory is in PATH
No virtual environment found
ppm init
pip-audit not found
pip install pip-audit
# or inside your venv:
ppm install pip-audit
Offline install fails
Make sure you've built the wheelhouse first:
ppm wheelhouse build
ppm install mypackage --offline
Slow installations
Use a faster mirror:
ppm config --set repository.index_url=https://pypi.tuna.tsinghua.edu.cn/simple
📋 Requirements
| Dependency | Version | Purpose |
|---|---|---|
typer[all] |
≥ 0.12 | CLI framework |
rich |
≥ 13.7 | Terminal formatting |
httpx[http2] |
≥ 0.27 | Async HTTP client |
pip-api |
≥ 0.0.30 | pip introspection |
packaging |
≥ 24.0 | Version parsing |
pip-audit |
≥ 2.7 | CVE scanning |
requirements-parser |
≥ 0.11 | requirements.txt parsing |
tomli-w |
≥ 1.0 | TOML writing |
platformdirs |
≥ 4.0 | Cross-platform paths |
aiofiles |
≥ 23.0 | Async file I/O |
📄 License
MIT License. See LICENSE for details.
Built with ❤️ by RootX for Python developers
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rootx_ppm-1.0.1.tar.gz.
File metadata
- Download URL: rootx_ppm-1.0.1.tar.gz
- Upload date:
- Size: 41.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9a62f8a45bfd4415877db6fcd76ed749387cfe9861712646515ace49251556d6
|
|
| MD5 |
d0b3e35ad2b382f91ccbc8c453c81d2a
|
|
| BLAKE2b-256 |
a6de2e7cd0a56381126a114b415953d10eee4a4cc8129f0c62465b9a252d6cfb
|
Provenance
The following attestation bundles were made for rootx_ppm-1.0.1.tar.gz:
Publisher:
publish.yml on Rootx202/PPM
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rootx_ppm-1.0.1.tar.gz -
Subject digest:
9a62f8a45bfd4415877db6fcd76ed749387cfe9861712646515ace49251556d6 - Sigstore transparency entry: 1609246029
- Sigstore integration time:
-
Permalink:
Rootx202/PPM@144aaf42052c60858f06ff169b9de6198342289b -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/Rootx202
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@144aaf42052c60858f06ff169b9de6198342289b -
Trigger Event:
release
-
Statement type:
File details
Details for the file rootx_ppm-1.0.1-py3-none-any.whl.
File metadata
- Download URL: rootx_ppm-1.0.1-py3-none-any.whl
- Upload date:
- Size: 45.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fc68068a598b8ac6fd94ed1b67ac26e65554da8617ceacd4f90598ea065725e8
|
|
| MD5 |
0bdf88a0f293814b8696f384a2a71965
|
|
| BLAKE2b-256 |
959e5635d349b1cffb6ea44c22154cf5b8a316ea367ba4acbb9675dc0a109bb8
|
Provenance
The following attestation bundles were made for rootx_ppm-1.0.1-py3-none-any.whl:
Publisher:
publish.yml on Rootx202/PPM
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rootx_ppm-1.0.1-py3-none-any.whl -
Subject digest:
fc68068a598b8ac6fd94ed1b67ac26e65554da8617ceacd4f90598ea065725e8 - Sigstore transparency entry: 1609246170
- Sigstore integration time:
-
Permalink:
Rootx202/PPM@144aaf42052c60858f06ff169b9de6198342289b -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/Rootx202
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@144aaf42052c60858f06ff169b9de6198342289b -
Trigger Event:
release
-
Statement type: