Lightweight Virtual Environment Manager for Python
Refract centralizes your Python virtual environments in a single location, providing simple commands to create, manage, and switch between project contexts—without the complexity of traditional virtual environment tools.
Demo
Features
- Centralized Management: All environments stored in
~/.refract/envs/ - Simple Commands: Intuitive syntax that's easy to remember
- Global Access: Use
refractfrom anywhere in your system - Zero Dependencies: Only requires Python standard library
- Seamless Switching: Instant environment activation with new shell sessions
- Colored Prompts: Clear visual indication of active environment in shell prompt
- Clean Organization: Automatic directory structure management
Table of Contents
Installation
Refract itself depends only on Python's standard library. The refract command and refract install (shell integration) are separate steps.
macOS and Linux only. Windows is not supported.
Prerequisites
- Python 3.10 or higher
- bash or zsh
pip is optional. pipx is optional.
From source (Python 3 only)
Best for minimal servers that may not have pip:
git clone git@github.com:YakShavingCatHerder/refract.git
cd refract
./install.sh
source ~/.zshrc # bash: source ~/.bashrc
This copies refract.py to ~/.local/bin/refract, then runs refract install.
From source with pip
git clone git@github.com:YakShavingCatHerder/refract.git
cd refract
./install.sh --pip
source ~/.zshrc # bash: source ~/.bashrc
From source with pipx (optional)
./install.sh --pipx
source ~/.zshrc # bash: source ~/.bashrc
From PyPI
The distribution name is refract-venv. The command is refract.
pip install refract-venv
refract install
source ~/.zshrc # bash: source ~/.bashrc
If you already use pipx for CLI tools:
pipx install refract-venv
refract install
source ~/.zshrc # bash: source ~/.bashrc
What refract install does
- Creates
~/.refract/andrefract.json(default colorway: green/black) - Installs prompt integration in
~/.zshrcand~/.bashrc - Installs the shell wrapper in both files (reloads after
refract colorway) - Tells you to restart or source your shell
It does not install the refract executable. Re-running it is idempotent: existing snippets are updated, not duplicated.
Uninstall
From a source checkout:
./uninstall.sh
If you installed the package:
pip uninstall refract-venv
# or: pipx uninstall refract-venv
Virtual environments in ~/.refract/envs/ are left in place. Remove them with rm -rf ~/.refract.
Quick Start
After installation, you can immediately start using refract:
# Create your first environment
refract init myproject
# List all environments
refract list
# Activate an environment
refract use myproject
# Remove an environment when done
refract rm myproject
Commands Reference
refract init <name>
Creates a new virtual environment with the specified name.
Parameters:
environment_name: Must be a valid Python identifier (letters, numbers, underscores only)
Example:
$ refract init django_project
Created new virtualenv at /path/to/.refract/envs/django_project
What happens:
- Creates a new virtual environment in
~/.refract/envs/<name>/ - Uses Python's built-in
venvmodule - Validates the environment name format
- Prevents duplicate environment creation
refract list
Displays all available virtual environments.
Example Output:
$ refract list
Available virtualenvs:
* django_project
* flask_api
* data_analysis
* machine_learning
What happens:
- Scans
~/.refract/envs/directory - Lists all subdirectories as available environments
- Shows helpful message if no environments exist
refract use <name>
Activates the specified virtual environment by opening a new shell session.
Example:
$ refract use django_project
[refract] Switching to environment 'django_project'...
What happens:
- Validates the environment exists
- Creates a temporary activation script that:
- Sources your shell profile files (
.bash_profile,.zshrc, etc.) - Activates the virtual environment
- Opens a new shell session with the environment active
- Sets up colored prompt showing the active refract environment with
[refract:name]prefix
- Runs the script in a new shell process
- Removes the temporary script as a cleanup process
After activation, you'll see:
[refract:django_project] user@machine ~ %
refract rm <name>
Removes the specified virtual environment.
Example:
$ refract rm old_project
Removed environment 'old_project'
What happens:
- Validates the environment exists
- Completely removes the environment directory
- Provides confirmation message
refract current
Shows the currently active refract environment.
Example:
$ refract current
Currently in refract environment: django_project
What happens:
- Checks for the
REFRACT_ENVenvironment variable - Displays the active environment name in light gray if one is active
- Shows "No refract environment currently active" if none is active
refract install
Initializes Refract config and shell integration. The executable must already be on your PATH (via ./install.sh, pip, or pipx).
What happens:
- Creates
~/.refract/andrefract.jsonif needed - Writes prompt hooks and the shell wrapper into
~/.zshrcand~/.bashrc - Does not create a symlink or install the
refractcommand
Usage Examples
Example 1: Web Development Workflow
# Create environments for different projects
$ refract init frontend
Created new virtualenv at /Users/path/.refract/envs/frontend
$ refract init backend
Created new virtualenv at /Users/path/.refract/envs/backend
# List all environments
$ refract list
Available virtualenvs:
* frontend
* backend
# Switch to frontend work
$ refract use frontend
[refract] Switching to environment 'frontend'...
# In the new shell session:
[refract:frontend] $ npm install
[refract:frontend] $ npm start
# Switch to backend work (in another terminal)
$ refract use backend
[refract] Switching to environment 'backend'...
# In the new shell session:
[refract:backend] $ pip install django
[refract:backend] $ python manage.py runserver
Example 2: Data Science Workflow
# Create specialized environments
$ refract init data_analysis
$ refract init ml_experiment
$ refract init visualization
# Switch between different analysis contexts
$ refract use data_analysis
[refract:data_analysis] $ pip install pandas numpy matplotlib
$ refract use ml_experiment
[refract:ml_experiment] $ pip install scikit-learn tensorflow
$ refract use visualization
[refract:visualization] $ pip install plotly seaborn bokeh
Example 3: Project Cleanup
# List all environments
$ refract list
Available virtualenvs:
* old_project
* experiment_1
* experiment_2
* current_project
# Remove completed experiments
$ refract rm experiment_1
Removed environment 'experiment_1'
$ refract rm experiment_2
Removed environment 'experiment_2'
# Verify cleanup
$ refract list
Available virtualenvs:
* old_project
* current_project
Directory Structure
Refract creates and manages the following structure:
~/.refract/
├── envs/ # All virtual environments
│ ├── project_a/
│ │ ├── bin/
│ │ ├── lib/
│ │ └── ...
│ ├── project_b/
│ │ ├── bin/
│ │ ├── lib/
│ │ └── ...
│ └── ...
└── refract.json # Configuration file
Colored Prompts Feature
Refract automatically modifies your shell prompt to show the active environment:
- Format:
[refract:environment_name]appears at the beginning of your prompt - Color: Green background with black text by default to make current venv easily visible
- Shell Support: Works with both bash and zsh
- Environment Variable: Sets
REFRACT_ENVfor programmatic access
Troubleshooting
Common Issues
"command not found: refract"
Problem: The refract command isn't available globally.
Solution:
# From a source checkout, install the command then shell integration
./install.sh
# If the command exists but shell hooks do not
refract install
# Make sure ~/.local/bin is on PATH
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
Refract environment is active, but prompt prefix is missing
Problem: refract use <name> activates the environment, but [refract:<name>] is not shown in your prompt.
Why this happens: Some shell themes/frameworks rebuild the prompt and can override custom prompt text.
How to verify activation:
echo $REFRACT_ENV
which python
If active, REFRACT_ENV should contain your environment name and which python should point to ~/.refract/envs/<name>/bin/python.
"Permission denied: refract"
Problem: The installed script does not have execute permissions.
Solution:
chmod +x ~/.local/bin/refract
"Environment 'name' does not exist"
Problem: Trying to use an environment that hasn't been created.
Solution:
# Check available environments
refract list
# Create the environment first
refract init name
"Environment name must be a valid identifier"
Problem: Using invalid characters in environment names.
Solution: Use only letters, numbers, and underscores:
# Valid names
refract init my_project
refract init project123
refract init _private
# Invalid names
refract init my-project # hyphens not allowed
refract init "my project" # spaces not allowed
refract init my.project # dots not allowed
Debug Mode
Enable debug output to troubleshoot issues:
refract --debug list
This will show additional information about paths and configuration.
Manual Environment Management
If you need to manually manage environments:
# List all environments
ls ~/.refract/envs/
# Remove an environment manually
rm -rf ~/.refract/envs/environment_name
# Check refract configuration
cat ~/.refract/refract.json
Contributing
Development Setup
- Clone the repository
- Install from source:
./install.sh --pip
Testing
CLI tests use a temporary HOME and require refract on PATH (install the wheel or run ./install.sh --pip first):
python -m unittest discover -s tests -v -p 'test_cli.py'
./install.sh methods are tested in CI with REFRACT_TEST_INSTALL_SH=1.
Regenerate the README GIF with VHS:
./demo/record.sh
Code Style
- Follow PEP 8 guidelines
- Use descriptive variable names
- Add docstrings to functions
- Include error handling
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
- Built with 1 dependency: Python's standard library
- Inspired by the need for simpler, cli-native management of virtual environments; perfect for deploying to lightweight servers when needed
- Thanks to the Python community for the excellent
venvmodule; this isn't a diss, just a specific use-case ;)
**Happy coding with refract! **
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 refract_venv-0.1.0.tar.gz.
File metadata
- Download URL: refract_venv-0.1.0.tar.gz
- Upload date:
- Size: 16.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0afac20286c80e7010c49e27dc85815d47de92050db1f680e5f7567aa632dbe5
|
|
| MD5 |
8ba3ca5b4611b3e580d8fa22f65531e7
|
|
| BLAKE2b-256 |
4c8d464df98f18f4481026d380913c14212f481132388dfcbb653054a2cec6af
|
Provenance
The following attestation bundles were made for refract_venv-0.1.0.tar.gz:
Publisher:
release.yml on YakShavingCatHerder/refract
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
refract_venv-0.1.0.tar.gz -
Subject digest:
0afac20286c80e7010c49e27dc85815d47de92050db1f680e5f7567aa632dbe5 - Sigstore transparency entry: 2798028238
- Sigstore integration time:
-
Permalink:
YakShavingCatHerder/refract@8a55339f4fea84c029f3ce734ec9863de22e4090 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/YakShavingCatHerder
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8a55339f4fea84c029f3ce734ec9863de22e4090 -
Trigger Event:
push
-
Statement type:
File details
Details for the file refract_venv-0.1.0-py3-none-any.whl.
File metadata
- Download URL: refract_venv-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2b38b2e26f22fd0caff0979ce0abd69420c39a8f0a692e475def493ad0f15998
|
|
| MD5 |
49ea7d641991c041c11eb253cba4b857
|
|
| BLAKE2b-256 |
fe0daef66609bfb4b9eb5bef67b1a0d43bb7ab706c1e777b928c3cea2882f931
|
Provenance
The following attestation bundles were made for refract_venv-0.1.0-py3-none-any.whl:
Publisher:
release.yml on YakShavingCatHerder/refract
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
refract_venv-0.1.0-py3-none-any.whl -
Subject digest:
2b38b2e26f22fd0caff0979ce0abd69420c39a8f0a692e475def493ad0f15998 - Sigstore transparency entry: 2798028337
- Sigstore integration time:
-
Permalink:
YakShavingCatHerder/refract@8a55339f4fea84c029f3ce734ec9863de22e4090 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/YakShavingCatHerder
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8a55339f4fea84c029f3ce734ec9863de22e4090 -
Trigger Event:
push
-
Statement type: