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
- Demo
- Installation
- Quick Start
- Commands Reference
- Usage Examples
- Troubleshooting
- Changelog
- Contributing
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
pipx is optional.
From source (Python 3 only)
Best for minimal servers that may not have pipx:
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 pipx (optional)
./install.sh --pipx
source ~/.zshrc # bash: source ~/.bashrc
From PyPI
The distribution name is refract-venv. The command is refract.
Prefer pipx. Homebrew’s pip3 will refuse to install into the system Python (PEP 668).
pipx install refract-venv
refract install
source ~/.zshrc # bash: source ~/.bashrc
If refract is not found after pipx install, ~/.local/bin is not on PATH yet:
pipx ensurepath
source ~/.zshrc # bash: source ~/.bashrc
refract install
source ~/.zshrc
pipx ensurepath only updates your shell config. Source or open a new terminal before refract will resolve. The second source loads the prompt hook that refract install just wrote.
What refract install does
- Creates
~/.refract/andrefract.json(default colorway: green/black; per-env colorways live underenvironments) - Installs prompt integration in
~/.zshrcand~/.bashrc - Installs the shell wrapper in both files (reloads colors after
refract colorwayin an active env) - 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:
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> [--color background/text]
Creates a new virtual environment with the specified name.
Parameters:
environment_name: Must be a valid Python identifier (letters, numbers, underscores only)--color background/text(optional): Per-env colorway, same asrefract colorway
Example:
$ refract init django_project
Created new virtualenv at /path/to/.refract/envs/django_project
$ refract init frontend --color black/red
Created new virtualenv at /path/to/.refract/envs/frontend
[refract] Colorway for environment 'frontend' set to black background with red text.
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
- Optional colorway is stored on that env in
refract.json
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
refract colorway <background>/<text> [env_name]
Sets prompt colors. The eight ANSI names are: black, red, green, yellow, blue, magenta, cyan, white.
Examples:
$ refract colorway green/black
[refract] Colorway for default set to green background with black text.
$ refract colorway blue/black frontend
[refract] Colorway for environment 'frontend' set to blue background with black text.
What happens:
- With no env name, updates the global default in
refract.json(used by envs that have no colorway of their own) - With an env name, or while
REFRACT_ENVis set, updates that environment only refract use <name>exportsREFRACT_BGandREFRACT_FGfor the prompt hook
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
Testing
CLI tests use a temporary HOME and require refract on PATH (install the wheel or run ./install.sh 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
Add user-facing changes under ## [Unreleased] in CHANGELOG.md. Move that block into a version heading when you tag.
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! **
Metadata
Release files for refract-venv 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| refract_venv-0.1.1.tar.gz | 19.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| refract_venv-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 31.9 kB
Release files / refract_venv-0.1.1.tar.gz
| Download URL | refract_venv-0.1.1.tar.gz |
|---|---|
| Size | 19.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
44a5c3f457cedd522ad20fb07f88eada5466c2e8fcc75504c2e6a8ea23466f3b
|
|
BLAKE2b-256 checksum How to use checksums |
949c553a7eaa3556509e91ea2722b4da5f3aeaef4236c9fb1db5cdbf4b301b2c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.
Transparency logRelease files / refract_venv-0.1.1-py3-none-any.whl
| Download URL | refract_venv-0.1.1-py3-none-any.whl |
|---|---|
| Size | 12.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7854e19380875c7e900c0bf8526ddb2713accfb25be23ec2e8556b415541e7ee
|
|
BLAKE2b-256 checksum How to use checksums |
982e6004449d879a3ca80b6126776dd58793482d4695dae853cf0d61e9a5bd98
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.
Transparency log