Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

439 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

scuv logo

๐Ÿจ scuv

โš ๏ธ Work in Progress โ€” Under active development. API may change.

๐Ÿ“ข Renamed in v0.15.0: the CLI command is now scuv (formerly scoop) โ€” renamed to coexist with Scoop, the Windows package manager. The crate/repo keep the name scoop-uv. Legacy SCOOP_*/.scoop-* settings are still read (with a deprecation warning) until v0.16.0 โ€” see the CHANGELOG for migration notes.

One scoop, endless envs โ€” pyenv-style Python environment manager powered by uv

CI Crates.io Downloads docs.rs

๐Ÿจ More badges

Security Coverage MSRV License Dependencies

Stars Forks Issues PRs Contributors

Last Commit Commit Activity Repo Size Top Language

Platform Rust Powered by uv Maintained PRs Welcome


What is scuv? ๐Ÿจ

scuv scoops up uv's blazing speed โ€” centralizing all your Python virtual environments in one place.

๐Ÿจ Think of it like running an ice cream parlor:

  • The Freezer (~/.scuv/) keeps all your flavors fresh
  • Flavors are your virtualenvs โ€” mix once, serve anywhere
  • One scoop is all you need to get the right env
The Old Way (Yuck ๐Ÿซ ) The scuv Way (Fresh ๐Ÿจ)
.venv scattered across projects ~/.scuv/virtualenvs/ centralized
Manual source .venv/bin/activate Auto-activate on directory entry
pyenv-virtualenv is slow uv-powered, 100x+ faster
Which Python? Which venv? Chaos. scuv doctor checks everything
Migrating envs? Manual nightmare. scuv migrate all does it all
English-only CLI Multi-language support (en, ko, ja, pt-BR)

60-Second Quick Start โšก

# 1. Install prerequisites
curl -LsSf https://astral.sh/uv/install.sh | sh  # uv
cargo install scoop-uv                           # installs the scuv command

# 2. Initialize your shell (zsh example)
echo 'eval "$(scuv init zsh)"' >> ~/.zshrc && source ~/.zshrc

# 3. Create your first environment
scuv install 3.12
scuv create myproject 3.12

# 4. Use it (auto-activates when you enter the directory!)
scuv use myproject
(myproject) $ pip install -r requirements.txt

That's it! ๐ŸŽ‰ Your environment is ready. For detailed docs, see Full Documentation โ†’

Set Python 3.11.0 as Global Default

Use this when you want new shell sessions to default to an environment built on Python 3.11.0:

scuv install 3.11.0
scuv create py311 3.11.0
scuv use py311 --global

This writes py311 to ~/.scuv/version. Priority still applies: SCUV_VERSION (shell override) and local .scuv-version take precedence.

Create a Project Env with Python 3.9.5

Use this when you want a new project environment pinned to an exact Python patch version:

scuv install 3.9.5
scuv create myproject 3.9.5
scuv info myproject

If 3.9.5 is missing, check available versions with uv python list and scuv list --pythons, then install and retry.

Uninstall Python + Associated Envs

Use this to remove one Python version and every environment using it:

# Optional preview
scuv list --python-version 3.12

# Remove Python 3.12 and all dependent environments
scuv uninstall 3.12 --cascade

# Verify cleanup
scuv list --pythons
scuv doctor

For CI/scripts, add --force to skip confirmation.

List Python Versions + Associated Envs

Use this to inspect what scuv currently manages:

# All managed Python versions
scuv list --pythons

# All environments and their Python versions
scuv list

# Environments associated with one Python version
scuv list --python-version 3.12

For scripts, use --json or --bare.

Integrate Custom or Pre-Existing Python

If the required version is not available from default scuv/uv sources:

# Recommended: explicit interpreter path
scuv create myenv --python-path /opt/python-debug/bin/python3

# Alternative: PATH-based discovery
export PATH="/opt/python-debug/bin:$PATH"
scuv create myenv 3.13

Verify integration with uv python list, scuv info myenv, and scuv doctor -v.

Project-Scoped Auto-Activation Control

Need temporary or directory-specific behavior without touching global settings?

# Temporary: current shell only
export SCUV_NO_AUTO=1
unset SCUV_NO_AUTO

# Directory-local behavior (writes .scuv-version in current directory)
scuv use system      # force system Python for this project
scuv use myproject   # pin this project to a specific env

# Terminal-only override (no file changes)
scuv shell system
scuv shell --unset

Installation ๐Ÿจ

Prerequisites

Dependency Install Why
uv (>= 0.5.14) curl -LsSf https://astral.sh/uv/install.sh | sh The secret ingredient ๐Ÿ”ฎ
Rust curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh Build from source

Minimum supported uv is 0.5.14. Run scuv doctor to verify your installation.

โ“ FAQ: How is scuv different from uv, and is it related to Scoop (Windows)?

How is scuv different from uv's centralized-project-envs preview?

They solve different problems, and scuv is built on top of uv โ€” it's a complement, not a fork or a competitor.

uv 0.11.25 added a preview feature (centralized-project-envs) that relocates a project's .venv into uv's cache directory. The environment is still bound to that one project: its identity is a cache key derived from the workspace path and interpreter (e.g. my-project-cp3.12.4-0123abcd), it cannot be shared between projects, there is no activation workflow, and uv cache clean / uv cache prune delete it unconditionally โ€” by design it is a disposable cache entry that gets transparently recreated.

scuv environments are the opposite in every one of those dimensions: named, durable, and project-independent.

uv centralized-project-envs scuv
Environment identity hash cache key (not user-controlled) a name you choose (scuv create ml 3.12)
Shared across projects no (key includes workspace path) yes โ€” any project with a .scuv-version file
Activation workflow none (uv run-centric; .venv link for IDEs) shell auto-activation, scuv use, 4 shells
Lifecycle wiped by uv cache clean/prune, auto-recreated durable; gc (dry-run first), verify, metadata (last_used)
Extras โ€” clone, diff, export/import, .scuv.toml sync, migration from pyenv / conda / virtualenvwrapper

The uv team has stated there are "no current plans to support standalone environments not tied to a specific project". That standalone, named, pyenv-virtualenv-style workflow is exactly what scuv provides โ€” with uv doing the fast parts underneath.

Is scuv related to Scoop, the Windows package manager?

No. scuv โ€” "a scoop of uv" ๐Ÿจ โ€” is a centralized Python virtual environment manager and is unrelated to Scoop, the Windows package manager. The project was originally command-named scoop; we renamed the command to scuv in v0.15.0 precisely so both tools can coexist cleanly on Windows. Installing scuv does not shadow or conflict with scoop in any shell, including PowerShell. (The repository and crate keep the historical name scoop-uv.)

Install scuv

cargo install scoop-uv  # installs the scuv command
๐Ÿ’ก scuv: command not found?

Cargo installs binaries to ~/.cargo/bin. Ensure it's in your PATH:

# Add to ~/.zshrc or ~/.bashrc
export PATH="$HOME/.cargo/bin:$PATH"

Or restart your terminal after installing Rust.

Upgrading from scoop (โ‰ค 0.14.x) ๐Ÿ”

The CLI command was renamed in v0.15.0 (scoop โ†’ scuv). One-time migration:

# 1. Update โ€” installs the new `scuv` binary
scoop self update        # or: cargo install scoop-uv
# ("could not locate the freshly installed `scoop` binary" warning is
#  expected across the rename โ€” the update itself already succeeded)

# 2. Remove the old binary if cargo left one behind
rm -f ~/.cargo/bin/scoop

# 3. Update your shell rc: scoop init โ†’ scuv init
#    ~/.zshrc / ~/.bashrc:  eval "$(scuv init zsh)"      # or bash
#    fish:                  scuv init fish | source

# 4. Move your freezer
mv ~/.scoop ~/.scuv

# 5. Restart your shell, then verify
scuv doctor              # flags anything left over

Legacy SCOOP_* env vars and .scoop-version / .scoop.toml files keep working (with a one-shot deprecation warning) until v0.16.0, and typing scoop in bash/zsh/fish still works through a deprecated forwarder that warns and calls scuv. Skipping step 2 is the one dangerous gap: a leftover old binary keeps running 0.14.x silently, without any warning.

Shell Setup

Step 1: Add to your shell config

Zsh (macOS default):

echo 'eval "$(scuv init zsh)"' >> ~/.zshrc
source ~/.zshrc

Bash:

echo 'eval "$(scuv init bash)"' >> ~/.bashrc
source ~/.bashrc

Fish:

echo 'scuv init fish | source' >> ~/.config/fish/config.fish
source ~/.config/fish/config.fish

PowerShell (Core or Windows PowerShell):

Add-Content $PROFILE 'Invoke-Expression (& scuv init powershell)'
. $PROFILE

Step 2: Verify

scuv --version
# โ†’ scuv 0.15.0 ๐Ÿจ

What this enables

  • โœ… Auto-activation โ€” enter a directory with .scuv-version, environment activates
  • โœ… Tab completion โ€” commands, environments, Python versions
  • โœ… Shell wrapper โ€” scuv activate/deactivate works correctly
  • โœ… Migration ready โ€” import from pyenv, conda, virtualenvwrapper
  • โœ… Multi-language โ€” English, ํ•œ๊ตญ์–ด, ๆ—ฅๆœฌ่ชž, Portuguรชs (BR)

Using with pyenv

Add scuv after pyenv in your rc file (order matters โ€” scuv gets the last scoop! ๐Ÿจ):

# ~/.zshrc
eval "$(pyenv init -)"       # 1. pyenv first
eval "$(scuv init zsh)"     # 2. scuv second

Options

Variable Effect
SCUV_NO_AUTO=1 Disable auto-activation
SCUV_HOME=/path Custom freezer location (default: ~/.scuv)
# Example: disable auto-activation
echo 'export SCUV_NO_AUTO=1' >> ~/.zshrc

The Freezer ๐ŸงŠ

Your ice cream parlor lives here:

~/.scuv/                    # ๐ŸงŠ The Freezer
โ”œโ”€โ”€ virtualenvs/             # ๐Ÿจ All your flavors
โ”‚   โ”œโ”€โ”€ myproject/           #    โ†’ Python 3.12 flavor
โ”‚   โ”œโ”€โ”€ webapp/              #    โ†’ Python 3.11 flavor
โ”‚   โ””โ”€โ”€ experiment/          #    โ†’ Python 3.13 flavor
โ””โ”€โ”€ version                  # ๐Ÿฅ„ Default scuv preference

Version file priority (first match wins):

SCUV_VERSION (env)  โ†’  "Override for this shell session" (set by scuv shell)
.scuv-version       โ†’  "I want THIS flavor here" (local + parent walk)
~/.scuv/version     โ†’  "My usual order" (global default)

Note: .python-version is not supported. Use .scuv-version for version pinning.


Commands ๐Ÿจ

Tip: Most commands support --json for machine-readable output.

Essential Commands

Command Description
scuv create <name> [version] Create a new environment
scuv use <name> Activate environment (auto-activates in directory)
scuv list List all environments (--sort name|created|last-used)
scuv status Show the currently active environment (includes Last used:)
scuv which <exe> Resolve an executable inside the active env
scuv run <env> -- <cmd> Run a command inside an env without activating
scuv sync Apply .scuv.toml (create env + install packages)
scuv export <name> Snapshot an env as portable JSON
scuv import <file> Recreate an env from an export file
scuv clone <src> <dst> Duplicate an environment
scuv diff <a> <b> Compare two environments (Python, packages, metadata)
scuv remove <name> Delete an environment
scuv install [version] Install Python version
scuv gc Garbage-collect orphan virtualenvs (--yes to remove, --older-than <n>d/w/y for stale envs)
scuv prune Prune the uv cache
scuv verify Per-env health check (metadata, python, pyvenv.cfg, ...)
scuv doctor Health check your setup
scuv self update Update scuv itself to the latest version

For the complete command reference, see Commands Documentation โ†’

๐Ÿ“– Full command reference (click to expand)

Everyday Scooping

Command Description
scuv create <name> [version] Mix a new flavor (default: latest Python)
scuv create <name> <ver> --install-python Mix a flavor, installing Python first if missing
scuv use <name> Pick your flavor (auto-activates)
scuv use <name> --link Also create .venv symlink for IDE
scuv use <name> --global Set as your usual order
scuv list What's in the freezer?
scuv list --pythons What Python versions do we have?
scuv list --sort last-used Newest activity first (also name / created)
scuv list --json Output as JSON
scuv info <name> Show detailed info (incl. Last used:)
scuv info <name> --json Output info as JSON
scuv status Which flavor am I scooping right now? (incl. Last used:)
scuv which <exe> Where's that scoop in my freezer?
scuv run <env> -- <cmd> Scoop on demand โ€” run without unpacking
scuv sync Read .scuv.toml and serve the flavor
scuv sync --with dev --dry-run Preview the plan, no scooping yet
scuv export <name> Bottle a flavor as portable JSON
scuv import <file> Unbottle it on another machine
scuv clone <src> <dst> Twin scoop โ€” same flavor, new cup
scuv diff <a> <b> Spot the difference between two flavors
scuv remove <name> Melt a flavor away

Managing the Freezer

Command Description
scuv install [version] Stock up on Python (default: latest)
scuv install --stable Get the oldest supported Python (3.10)
scuv uninstall <version> Remove a Python version

Health Check ๐Ÿฉบ

Command Description
scuv doctor Is everything fresh? Check your setup!
scuv doctor --fix Auto-fix issues where possible
scuv doctor --json Output diagnostics as JSON

Migration ๐Ÿšš

Command Description
scuv migrate list Show environments to migrate
scuv migrate @env <name> Migrate a single environment
scuv migrate all Migrate all environments (parallel)

Supported sources: pyenv-virtualenv, virtualenvwrapper, conda

Flags: --source {pyenv|virtualenvwrapper|conda}, --dry-run, --force, --yes, --strict, --delete-source, --json; @env also --rename/--auto-rename.

Cleanup ๐Ÿงน

Command Description
scuv verify Per-env health diagnosis โ€” 6 checks per env
scuv verify --strict Same, but exit 1 on any issue (CI gate)
scuv gc Preview orphan virtualenvs (missing metadata or broken Python)
scuv gc --yes Actually remove the orphans
scuv gc --aggressive Also flag unused uv-managed Python versions
scuv gc --older-than 30d Also flag envs idle past the cutoff (no last_used never matches)
scuv prune Prune the uv download/wheel cache (uv cache prune wrapper)

Packaging ๐Ÿ“ฆ

Command Description
scuv man Print top-level scuv.1 to stdout (pipe to man -l -)
scuv man <DIR> Write scuv.1 + one scuv-<sub>.1 per subcommand into <DIR>

Language ๐ŸŒ

Command Description
scuv lang Show current language
scuv lang <code> Set language (en, ko, ja, pt-BR)
scuv lang --list List supported languages
scuv lang --reset Reset to system default

๐ŸŒ Want to help translate? We welcome translations in any language! See #44 to contribute.

Shell Integration

Command Description
scuv init <shell> Output shell initialization script
scuv completions <shell> Generate completion script
scuv use system Switch to system Python
scuv shell <name> Set shell env (eval required)
scuv shell --unset Clear shell env setting

Shells supported: bash, zsh, fish, powershell


Documentation ๐Ÿ“š

๐Ÿ“– Read the Full Documentation โ†’

Guide Description
Installation Guide Prerequisites, shell setup, and troubleshooting
Quick Start Get productive in 5 minutes
Command Reference Detailed documentation for every command
Shell Integration Auto-activation, version files, and configuration
Migration Guide Move from pyenv, conda, or virtualenvwrapper
Contributing Development setup and contribution guidelines

Minimum Supported Rust Version (MSRV) ๐Ÿฆ€

Current MSRV: 1.88 (required by Rust Edition 2024)

scuv follows an N-1 MSRV policy โ€” we support the current stable Rust and one previous version (~6 week lag).

User Type MSRV Impact Action
Binary users โœ… None Download from releases or cargo install
Source builders โš ๏ธ Rust >= 1.88 required Run rustup update if needed
Contributors ๐Ÿ”ง Test on MSRV before PR cargo +1.88 test --all-features
๐Ÿ“‹ Full MSRV policy (click to expand)

About N-1 Policy

We support the current stable Rust and one previous version (~6 week lag). MSRV updates are considered non-breaking for binary users per Cargo RFC 3537.

When We Bump MSRV

โœ… We bump when:

  • New Rust features provide significant user benefits
  • Critical dependencies require newer versions
  • Security fixes only available in newer Rust

โŒ We don't bump for:

  • Time-based schedules without clear benefits
  • Minor syntax sugar or aesthetic preferences
  • Personal developer preferences

All MSRV changes are documented in CHANGELOG.md with clear rationale.

Edition 2024 Constraints

scuv uses Rust Edition 2024, which requires:

  • Minimum Rust 1.85 (hard floor)
  • MSRV-aware resolver enabled by default
  • Cannot downgrade below 1.85 without changing edition to 2021

Automation

  • CI: Tests on both MSRV (1.88) and stable automatically
  • cargo-msrv: Verifies MSRV on Cargo.toml changes in CI
  • Badge: README badge auto-updates from Cargo.toml via shields.io
  • Local: rust-toolchain.toml auto-selects 1.88 in project directory

For more details, see our MSRV bump guide in CONTRIBUTING.md.


๐Ÿ—๏ธ Architecture (for contributors and curious minds)

Built with Rust for speed and reliability:

src/
โ”œโ”€โ”€ cli/           # ๐ŸŽฎ Command parsing (clap)
โ”‚   โ””โ”€โ”€ commands/  # Individual command handlers
โ”œโ”€โ”€ core/          # ๐Ÿง  Domain logic
โ”‚   โ”œโ”€โ”€ version    # Version file resolution
โ”‚   โ”œโ”€โ”€ metadata   # Virtualenv metadata (JSON)
โ”‚   โ”œโ”€โ”€ virtualenv # Virtualenv entity
โ”‚   โ”œโ”€โ”€ doctor     # Health diagnostics
โ”‚   โ””โ”€โ”€ migrate/   # Migration (pyenv, conda, venvwrapper)
โ”œโ”€โ”€ shell/         # ๐Ÿš Shell integration (bash, zsh, fish, powershell)
โ”œโ”€โ”€ uv/            # โšก uv CLI wrapper
โ”œโ”€โ”€ output/        # ๐ŸŽจ Terminal UI & JSON output
โ”œโ”€โ”€ i18n.rs        # ๐ŸŒ Internationalization (en, ko, ja, pt-BR)
โ”œโ”€โ”€ config.rs      # โš™๏ธ User configuration
โ””โ”€โ”€ error, paths, validate  # Utilities

Design principle: The CLI outputs shell code to stdout, your shell evaluates it. Just like pyenv โ€” battle-tested pattern.


License

Licensed under either of:

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this work shall be dual licensed as above, without any additional terms or conditions.


Support ๐Ÿจ

If you find this project useful, consider buying me a coffee (or an ice cream ๐Ÿจ)!

Buy Me A Coffee


Contributors โœจ

Thanks goes to these wonderful people (emoji key):

azamarassy
azamarassy

๐ŸŒ
Murillo Bazilio
Murillo Bazilio

๐ŸŒ
Tosinibikunle
Tosinibikunle

๐Ÿ“–

Acknowledgments ๐Ÿจ

This project stands on the shoulders of giants:

  • uv by Astral โ€” The blazing-fast Python package manager that powers scuv's backend. Without uv's incredible speed and reliability, scuv wouldn't exist. Thank you to Charlie Marsh and the entire Astral team for revolutionizing Python tooling.

  • pyenv & pyenv-virtualenv โ€” The original inspiration for scuv's workflow. pyenv taught us how Python version management should feel, and pyenv-virtualenv showed us how to centralize virtual environments elegantly.

  • virtualenv by PyPA โ€” The pioneer of Python virtual environments. Thank you to Ian Bicking for the original concept that changed how we isolate Python projects.

  • Python โ€” The language that made programming accessible to everyone. scuv exists to make Python development even more delightful. Thank you to Guido van Rossum and the Python community.

  • Rust โ€” The language that makes scuv fast, safe, and reliable. Thank you to the Rust team and Ferris ๐Ÿฆ€ for proving that systems programming can be both powerful and enjoyable.


scuv ferris

I built scuv because I needed it โ€” and now it's yours too. ๐Ÿจ

Grab a scoop, enjoy the flavor, and if you have thoughts to share, the door to the ice cream parlor is always open.

Issues ยท Discussions ยท PRs Welcome

About

๐Ÿจ One scoop, endless envs โ€” centralized Python virtual environment manager with auto-activation โšก

Topics

Resources

Contributing

Security policy

Stars

Watchers

Forks

Releases

Sponsor this project

Packages

Contributors

Languages