envlit¶
A simple CLI tool to organize, load, and switch between your project's environment variable contexts.
Use Cases¶
- Development environments - Switch between dev/prod configs
- ML/AI workflows - Conveniently manage CUDA devices, model paths, backends, environment variables
- Multi-project setup - Isolated environments per project
- Team consistency - Share common environment configs via git, while keeping local overrides
Installation¶
Quick Start¶
Initialize envlit in your shell (add to .bashrc or .zshrc):
Create a config file at .envlit/default.yaml:
Load and unload environment variables:
el # Load default profile
echo $PROJECT_MODE # Output: Development (variable set by envlit)
echo $DEBUG # Output: true (variable set by envlit)
eul # Unload environment variables
echo $PROJECT_MODE # Output: (empty - variable restored to original state)
echo $DEBUG # Output: (empty - variable restored to original state)
Features¶
Smart State Tracking¶
Automatically detects and preserves manual environment changes between load/unload cycles. Won't overwrite variables you've modified.
Example:
el dev # Load dev environment (sets DEBUG=true)
export DEBUG=false # Manually change DEBUG
export CUSTOM_VAR=foo # Add your own variable
eul # Unload: restores original DEBUG, keeps CUSTOM_VAR
envlit only restores variables it managed, preserving your manual changes.
Dynamic Flags¶
Define short CLI flags in YAML that map to long environment variable names and values. Reduces typing burden:
flags:
cuda:
flag: ["--cuda", "-g"]
default: "0"
target: "CUDA_VISIBLE_DEVICES"
backend:
flag: ["--backend", "-b"]
default: "c"
target: "ML_COMPUTE_BACKEND"
map:
c: "CPU"
g: "GPU"
t: "TPU"
Usage: el dev --cuda 2 -b g sets CUDA_VISIBLE_DEVICES=2 and ML_COMPUTE_BACKEND=GPU
Environment Variable Operations¶
envlit supports three syntaxes for setting environment variables:
1. String shortcut (for simple set operations):
2. Dict with single operation:
3. List of operations (pipeline):
env:
PATH:
- op: remove
value: "/old/path"
- op: prepend
value: "./bin"
- op: append
value: "/usr/local/tools"
Available operations:
- set - Set a value (string shortcut available)
- unset - Unset a variable
- prepend - Add to front of path-like variable
- append - Add to end of path-like variable
- remove - Remove from path-like variable
Lifecycle Hooks¶
Execute custom scripts at four lifecycle points:
hooks:
pre_load:
- name: "Validate setup"
script: "echo 'Loading...'"
post_load:
- name: "Show status"
script: "echo 'Ready!'"
pre_unload:
- name: "Cleanup"
script: |
echo "Unloading..."
echo "Goodbye!"
post_unload:
- name: "Confirm"
script: "echo 'Environment restored.'"
Config Inheritance¶
Extend base configurations to reduce duplication:
Special Characters in Values
Variable Expansion: Use shell syntax
$VARor${VAR}- Expands at runtime${VAR:-default}- With default value
Literal Dollar Sign: Use placeholder
{{DOLLAR}}- Becomes literal$- Example:
PRICE: "{{DOLLAR}}100"→$100
Other Special Characters:
- Backticks, quotes, backslashes are auto-escaped
- Use YAML quote alternation for quotes:
"value 'with' singles"'value "with" doubles'
Examples:
| Input (YAML) | Output in Script | Shell Interprets | Use Case |
|---|---|---|---|
$HOME |
$HOME |
/Users/you |
Variable expansion |
${HOME} |
${HOME} |
/Users/you |
Variable expansion |
{{DOLLAR}}100 |
\$100 |
$100 |
Literal dollar |
`cmd` |
\`cmd\` |
`cmd` |
Literal backtick |
"quoted" |
\"quoted\" |
"quoted" |
Escaped quotes |
For complex logic: Use hooks instead of env: section
Multiple Profiles¶
Switch between dev, test, and prod environments:
Configuration¶
Create .envlit/<profile>.yaml files:
# Optional: Inherit from base config
extends: "./base.yaml"
# Dynamic CLI flags - short flags map to long env var names and values
flags:
cuda:
flag: ["--cuda", "-g"]
default: "0"
target: "CUDA_VISIBLE_DEVICES"
backend:
flag: ["--backend", "-b"]
default: "c"
target: "ML_COMPUTE_BACKEND"
map:
c: "CPU"
g: "GPU"
t: "TPU"
# Environment variables
env:
# Simple values (string shortcut for 'set' operation)
DEBUG: "true"
API_URL: "https://api.example.com"
# Unset variables
LEGACY_VAR:
op: unset
# Shell expansion
DATA_PATH: "${HOME}/data"
# Single operation (dict syntax)
PRODUCTION_MODE:
op: set
value: "true"
# Path operations (list of operations - pipeline)
PATH:
- op: remove
value: "/deprecated/path"
- op: prepend
value: "./bin"
- op: append
value: "/usr/local/tools"
# Single path operation (dict syntax)
PYTHONPATH:
op: prepend
value: "./src"
# Lifecycle hooks
hooks:
pre_load:
- name: "Check dependencies"
script: "command -v docker >/dev/null || echo 'Warning: docker not found'"
post_load:
- name: "Show environment"
script: "echo '✓ Environment loaded'"
pre_unload:
- name: "Cleanup"
script: "echo 'Unloading...'"
post_unload:
- name: "Confirm"
script: "echo '✓ Environment restored'"
Commands¶
# Initialize shell integration
eval "$(envlit init)"
# Load environments
el # Load default profile
el dev # Load dev profile
el dev --cuda 1 # Load with flags
# Unload environment
eul
# Export tracked variables to .env file
envlit state # Show variables from envlit's state
envlit state --from-env # Show current environment values
envlit state > .env # Export to .env file
# Check installation
envlit doctor
Shell Integration¶
The init command creates shell functions that wrap envlit:
- el - Load environment
- eul - Unload environment
Customize aliases during initialization:
How It Works¶
- Load Phase:
- Captures current environment state (snapshot A)
- Runs pre-load hooks
- Exports environment variables
- Runs post-load hooks
-
Captures new state (snapshot B) and saves difference
-
Unload Phase:
- Runs pre-unload hooks
- Restores original environment from saved state
-
Runs post-unload hooks
-
State Tracking:
- Detects manual changes between snapshots
- Preserves user modifications during unload
- Only restores variables changed by envlit (Note: those changed during hooks are not tracked, and should be taken care of in hooks themselves)