Skip to main content
Screenshot 2026-08-18 at 20 58 54

Lightweight Virtual Environment Manager for Python

CI PyPI Python License: MIT

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

refract demo

Features

  • Centralized Management: All environments stored in ~/.refract/envs/
  • Simple Commands: Intuitive syntax that's easy to remember
  • Global Access: Use refract from 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

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/ and refract.json (default colorway: green/black; per-env colorways live under environments)
  • Installs prompt integration in ~/.zshrc and ~/.bashrc
  • Installs the shell wrapper in both files (reloads colors after refract colorway in 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 as refract 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 venv module
  • 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:

  1. Validates the environment exists
  2. 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
  1. Runs the script in a new shell process
  2. 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_ENV environment 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/ and refract.json if needed
  • Writes prompt hooks and the shell wrapper into ~/.zshrc and ~/.bashrc
  • Does not create a symlink or install the refract command

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_ENV is set, updates that environment only
  • refract use <name> exports REFRACT_BG and REFRACT_FG for 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_ENV for 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

  1. Clone the repository
  2. 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 venv module; 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)

Source distribution for refract-venv 0.1.1
File Size Uploaded
refract_venv-0.1.1.tar.gz 19.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for refract-venv 0.1.1
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page